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
15namespace 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//
58class 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