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 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: 125 AllocationScope() {} 126 ~AllocationScope() {} 127 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