// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_ #define CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_ #include <queue> #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "base/memory/shared_memory.h" #include "content/common/content_export.h" namespace content { // ResourceBuffer implements a simple "circular buffer" allocation strategy. // Allocations are recycled in FIFO order. // // You can think of the ResourceBuffer as a FIFO. The Allocate method reserves // space in the buffer. Allocate may be called multiple times until the buffer // is fully reserved (at which point CanAllocate returns false). Allocations // are freed in FIFO order via a call to RecycleLeastRecentlyAllocated. // // ResourceBuffer is reference-counted for the benefit of consumers, who need // to ensure that ResourceBuffer stays alive while they are using its memory. // // EXAMPLE USAGE: // // // Writes data into the ResourceBuffer, and returns the location (byte // // offset and count) of the bytes written into the ResourceBuffer's shared // // memory buffer. // void WriteToBuffer(ResourceBuffer* buf, int* offset, int* count) { // DCHECK(buf->CanAllocate()); // // *offset = -1; // *count = 0; // // int size; // char* ptr = buf->Allocate(&size); // if (!ptr) { /* handle error */ } // // int bytes_read = static_cast<int>(fread(ptr, 1, size, file_pointer_)); // if (!bytes_read) { /* handle error */ } // // if (bytes_read < size) // buf->ShrinkLastAllocation(bytes_read); // // *offset = buf->GetLastAllocationOffset(); // *count = bytes_read; // } // // NOTE: As the above example illustrates, the ResourceBuffer keeps track of // the last allocation made. Calling ShrinkLastAllocation is optional, as it // just helps the ResourceBuffer optimize storage and be more aggressive about // returning larger allocations from the Allocate method. // class CONTENT_EXPORT ResourceBuffer : public base::RefCountedThreadSafe<ResourceBuffer> { public: ResourceBuffer(); // Initialize the shared memory buffer. It will be buffer_size bytes in // length. The min/max_allocation_size parameters control the behavior of // the Allocate method. It will prefer to return segments that are // max_allocation_size in length, but will return segments less than that if // space is limited. It will not return allocations smaller than // min_allocation_size. bool Initialize(int buffer_size, int min_allocation_size, int max_allocation_size); bool IsInitialized() const; // Returns a shared memory handle that can be passed to the given process. // The shared memory handle is only intended to be interpretted by code // running in the specified process. NOTE: The caller should ensure that // this memory eventually be returned to the operating system. bool ShareToProcess(base::ProcessHandle process_handle, base::SharedMemoryHandle* shared_memory_handle, int* shared_memory_size); // Returns true if Allocate will succeed. bool CanAllocate() const; // Returns a pointer into the shared memory buffer or NULL if the buffer is // already fully allocated. The returned size will be max_allocation_size // unless the buffer is close to being full. char* Allocate(int* size); // Returns the offset into the shared memory buffer where the last allocation // returned by Allocate can be found. int GetLastAllocationOffset() const; // Called to reduce the size of the last allocation returned by Allocate. It // is OK for new_size to match the current size of the last allocation. void ShrinkLastAllocation(int new_size); // Called to allow reuse of memory that was previously allocated. See notes // above the class for more details about this method. void RecycleLeastRecentlyAllocated(); private: friend class base::RefCountedThreadSafe<ResourceBuffer>; ~ResourceBuffer(); base::SharedMemory shared_mem_; int buf_size_; int min_alloc_size_; int max_alloc_size_; // These point to the range of the shared memory that is currently allocated. // If alloc_start_ is -1, then the range is empty and nothing is allocated. // Otherwise, alloc_start_ points to the start of the allocated range, and // alloc_end_ points just beyond the end of the previous allocation. In the // wraparound case, alloc_end_ <= alloc_start_. See resource_buffer.cc for // more details about these members. int alloc_start_; int alloc_end_; std::queue<int> alloc_sizes_; DISALLOW_COPY_AND_ASSIGN(ResourceBuffer); }; } // namespace content #endif // CONTENT_BROWSER_LOADER_RESOURCE_BUFFER_H_