Home | History | Annotate | Download | only in loader
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
      6 #define CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
      7 
      8 #include <queue>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/memory/shared_memory.h"
     13 #include "content/common/content_export.h"
     14 
     15 namespace content {
     16 
     17 // ResourceBuffer implements a simple "circular buffer" allocation strategy.
     18 // Allocations are recycled in FIFO order.
     19 //
     20 // You can think of the ResourceBuffer as a FIFO.  The Allocate method reserves
     21 // space in the buffer.  Allocate may be called multiple times until the buffer
     22 // is fully reserved (at which point CanAllocate returns false).  Allocations
     23 // are freed in FIFO order via a call to RecycleLeastRecentlyAllocated.
     24 //
     25 // ResourceBuffer is reference-counted for the benefit of consumers, who need
     26 // to ensure that ResourceBuffer stays alive while they are using its memory.
     27 //
     28 // EXAMPLE USAGE:
     29 //
     30 //   // Writes data into the ResourceBuffer, and returns the location (byte
     31 //   // offset and count) of the bytes written into the ResourceBuffer's shared
     32 //   // memory buffer.
     33 //   void WriteToBuffer(ResourceBuffer* buf, int* offset, int* count) {
     34 //     DCHECK(buf->CanAllocate());
     35 //
     36 //     *offset = -1;
     37 //     *count = 0;
     38 //
     39 //     int size;
     40 //     char* ptr = buf->Allocate(&size);
     41 //     if (!ptr) { /* handle error */ }
     42 //
     43 //     int bytes_read = static_cast<int>(fread(ptr, 1, size, file_pointer_));
     44 //     if (!bytes_read) { /* handle error */ }
     45 //
     46 //     if (bytes_read < size)
     47 //       buf->ShrinkLastAllocation(bytes_read);
     48 //
     49 //     *offset = buf->GetLastAllocationOffset();
     50 //     *count = bytes_read;
     51 //   }
     52 //
     53 // NOTE: As the above example illustrates, the ResourceBuffer keeps track of
     54 // the last allocation made.  Calling ShrinkLastAllocation is optional, as it
     55 // just helps the ResourceBuffer optimize storage and be more aggressive about
     56 // returning larger allocations from the Allocate method.
     57 //
     58 class CONTENT_EXPORT ResourceBuffer
     59     : public base::RefCountedThreadSafe<ResourceBuffer> {
     60  public:
     61   ResourceBuffer();
     62 
     63   // Initialize the shared memory buffer.  It will be buffer_size bytes in
     64   // length.  The min/max_allocation_size parameters control the behavior of
     65   // the Allocate method.  It will prefer to return segments that are
     66   // max_allocation_size in length, but will return segments less than that if
     67   // space is limited.  It will not return allocations smaller than
     68   // min_allocation_size.
     69   bool Initialize(int buffer_size,
     70                   int min_allocation_size,
     71                   int max_allocation_size);
     72   bool IsInitialized() const;
     73 
     74   // Returns a shared memory handle that can be passed to the given process.
     75   // The shared memory handle is only intended to be interpretted by code
     76   // running in the specified process.  NOTE: The caller should ensure that
     77   // this memory eventually be returned to the operating system.
     78   bool ShareToProcess(base::ProcessHandle process_handle,
     79                       base::SharedMemoryHandle* shared_memory_handle,
     80                       int* shared_memory_size);
     81 
     82   // Returns true if Allocate will succeed.
     83   bool CanAllocate() const;
     84 
     85   // Returns a pointer into the shared memory buffer or NULL if the buffer is
     86   // already fully allocated.  The returned size will be max_allocation_size
     87   // unless the buffer is close to being full.
     88   char* Allocate(int* size);
     89 
     90   // Returns the offset into the shared memory buffer where the last allocation
     91   // returned by Allocate can be found.
     92   int GetLastAllocationOffset() const;
     93 
     94   // Called to reduce the size of the last allocation returned by Allocate.  It
     95   // is OK for new_size to match the current size of the last allocation.
     96   void ShrinkLastAllocation(int new_size);
     97 
     98   // Called to allow reuse of memory that was previously allocated.  See notes
     99   // above the class for more details about this method.
    100   void RecycleLeastRecentlyAllocated();
    101 
    102  private:
    103   friend class base::RefCountedThreadSafe<ResourceBuffer>;
    104   ~ResourceBuffer();
    105 
    106   base::SharedMemory shared_mem_;
    107 
    108   int buf_size_;
    109   int min_alloc_size_;
    110   int max_alloc_size_;
    111 
    112   // These point to the range of the shared memory that is currently allocated.
    113   // If alloc_start_ is -1, then the range is empty and nothing is allocated.
    114   // Otherwise, alloc_start_ points to the start of the allocated range, and
    115   // alloc_end_ points just beyond the end of the previous allocation.  In the
    116   // wraparound case, alloc_end_ <= alloc_start_.  See resource_buffer.cc for
    117   // more details about these members.
    118   int alloc_start_;
    119   int alloc_end_;
    120 
    121   std::queue<int> alloc_sizes_;
    122 
    123   DISALLOW_COPY_AND_ASSIGN(ResourceBuffer);
    124 };
    125 
    126 }  // namespace content
    127 
    128 #endif  // CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_
    129