• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 MOJO_PUBLIC_BINDINGS_LIB_BUFFER_H_
6 #define MOJO_PUBLIC_BINDINGS_LIB_BUFFER_H_
7 
8 #include <stddef.h>
9 
10 #include <deque>
11 
12 #include "mojo/public/system/macros.h"
13 
14 namespace mojo {
15 
16 // Buffer provides a way to allocate memory. Allocations are 8-byte aligned and
17 // zero-initialized. Allocations remain valid for the lifetime of the Buffer.
18 class Buffer {
19  public:
20   typedef void (*Destructor)(void* address);
21 
22   Buffer();
23   virtual ~Buffer();
24 
25   virtual void* Allocate(size_t num_bytes, Destructor func = NULL) = 0;
26 
27   static Buffer* current();
28 
29  private:
30   Buffer* previous_;
31 };
32 
33 namespace internal {
34 
35 // The following class is designed to be allocated on the stack.  If necessary,
36 // it will failover to allocating objects on the heap.
37 class ScratchBuffer : public Buffer {
38  public:
39   ScratchBuffer();
40   virtual ~ScratchBuffer();
41 
42   virtual void* Allocate(size_t num_bytes, Destructor func = NULL)
43       MOJO_OVERRIDE;
44 
45  private:
46   enum { kMinSegmentSize = 512 };
47 
48   struct Segment {
49     Segment* next;
50     char* cursor;
51     char* end;
52   };
53 
54   void* AllocateInSegment(Segment* segment, size_t num_bytes);
55   void AddOverflowSegment(size_t delta);
56 
57   char fixed_data_[kMinSegmentSize];
58   Segment fixed_;
59   Segment* overflow_;
60 
61   struct PendingDestructor {
62     Destructor func;
63     void* address;
64   };
65   std::deque<PendingDestructor> pending_dtors_;
66 
67   MOJO_DISALLOW_COPY_AND_ASSIGN(ScratchBuffer);
68 };
69 
70 // FixedBuffer provides a simple way to allocate objects within a fixed chunk
71 // of memory. Objects are allocated by calling the |Allocate| method, which
72 // extends the buffer accordingly. Objects allocated in this way are not freed
73 // explicitly. Instead, they remain valid so long as the FixedBuffer remains
74 // valid.  The Leak method may be used to steal the underlying memory from the
75 // FixedBuffer.
76 //
77 // Typical usage:
78 //
79 //   {
80 //     FixedBuffer buf(8 + 8);
81 //
82 //     int* a = static_cast<int*>(buf->Allocate(sizeof(int)));
83 //     *a = 2;
84 //
85 //     double* b = static_cast<double*>(buf->Allocate(sizeof(double)));
86 //     *b = 3.14f;
87 //
88 //     void* data = buf.Leak();
89 //     Process(data);
90 //
91 //     free(data);
92 //   }
93 //
94 class FixedBuffer : public Buffer {
95  public:
96   explicit FixedBuffer(size_t size);
97   virtual ~FixedBuffer();
98 
99   // Grows the buffer by |num_bytes| and returns a pointer to the start of the
100   // addition. The resulting address is 8-byte aligned, and the content of the
101   // memory is zero-filled.
102   virtual void* Allocate(size_t num_bytes, Destructor func = NULL)
103       MOJO_OVERRIDE;
104 
size()105   size_t size() const { return size_; }
106 
107   // Returns the internal memory owned by the Buffer to the caller. The Buffer
108   // relinquishes its pointer, effectively resetting the state of the Buffer
109   // and leaving the caller responsible for freeing the returned memory address
110   // when no longer needed.
111   void* Leak();
112 
113  private:
114   char* ptr_;
115   size_t cursor_;
116   size_t size_;
117 
118   MOJO_DISALLOW_COPY_AND_ASSIGN(FixedBuffer);
119 };
120 
121 }  // namespace internal
122 
123 class AllocationScope {
124  public:
AllocationScope()125   AllocationScope() {}
~AllocationScope()126   ~AllocationScope() {}
127 
buffer()128   Buffer* buffer() { return &buffer_; }
129 
130  private:
131   internal::ScratchBuffer buffer_;
132 
133   MOJO_DISALLOW_COPY_AND_ASSIGN(AllocationScope);
134 };
135 
136 }  // namespace mojo
137 
138 #endif  // MOJO_PUBLIC_BINDINGS_LIB_BUFFER_H_
139