NDDEM
allocators.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef CEREAL_RAPIDJSON_ALLOCATORS_H_
16 #define CEREAL_RAPIDJSON_ALLOCATORS_H_
17 
18 #include "rapidjson.h"
19 
21 
23 // Allocator
24 
63 #ifndef CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
64 #define CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
65 #endif
66 
67 
69 // CrtAllocator
70 
72 
75 class CrtAllocator {
76 public:
77  static const bool kNeedFree = true;
78  void* Malloc(size_t size) {
79  if (size) // behavior of malloc(0) is implementation defined.
80  return std::malloc(size);
81  else
82  return NULL; // standardize to returning NULL.
83  }
84  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
85  (void)originalSize;
86  if (newSize == 0) {
87  std::free(originalPtr);
88  return NULL;
89  }
90  return std::realloc(originalPtr, newSize);
91  }
92  static void Free(void *ptr) { std::free(ptr); }
93 };
94 
96 // MemoryPoolAllocator
97 
99 
114 template <typename BaseAllocator = CrtAllocator>
116 public:
117  static const bool kNeedFree = false;
118 
120 
123  MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
124  chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
125  {
126  }
127 
129 
138  MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
139  chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
140  {
141  CEREAL_RAPIDJSON_ASSERT(buffer != 0);
142  CEREAL_RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
143  chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
144  chunkHead_->capacity = size - sizeof(ChunkHeader);
145  chunkHead_->size = 0;
146  chunkHead_->next = 0;
147  }
148 
150 
153  Clear();
155  }
156 
158  void Clear() {
159  while (chunkHead_ && chunkHead_ != userBuffer_) {
160  ChunkHeader* next = chunkHead_->next;
161  baseAllocator_->Free(chunkHead_);
162  chunkHead_ = next;
163  }
165  chunkHead_->size = 0; // Clear user buffer
166  }
167 
169 
171  size_t Capacity() const {
172  size_t capacity = 0;
173  for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
174  capacity += c->capacity;
175  return capacity;
176  }
177 
179 
181  size_t Size() const {
182  size_t size = 0;
183  for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
184  size += c->size;
185  return size;
186  }
187 
189  void* Malloc(size_t size) {
190  if (!size)
191  return NULL;
192 
193  size = CEREAL_RAPIDJSON_ALIGN(size);
194  if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
195  if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
196  return NULL;
197 
198  void *buffer = reinterpret_cast<char *>(chunkHead_) + CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
199  chunkHead_->size += size;
200  return buffer;
201  }
202 
204  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
205  if (originalPtr == 0)
206  return Malloc(newSize);
207 
208  if (newSize == 0)
209  return NULL;
210 
211  originalSize = CEREAL_RAPIDJSON_ALIGN(originalSize);
212  newSize = CEREAL_RAPIDJSON_ALIGN(newSize);
213 
214  // Do not shrink if new size is smaller than original
215  if (originalSize >= newSize)
216  return originalPtr;
217 
218  // Simply expand it if it is the last allocation and there is sufficient space
219  if (originalPtr == reinterpret_cast<char *>(chunkHead_) + CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
220  size_t increment = static_cast<size_t>(newSize - originalSize);
221  if (chunkHead_->size + increment <= chunkHead_->capacity) {
222  chunkHead_->size += increment;
223  return originalPtr;
224  }
225  }
226 
227  // Realloc process: allocate and copy memory, do not free original buffer.
228  if (void* newBuffer = Malloc(newSize)) {
229  if (originalSize)
230  std::memcpy(newBuffer, originalPtr, originalSize);
231  return newBuffer;
232  }
233  else
234  return NULL;
235  }
236 
238  static void Free(void *ptr) { (void)ptr; } // Do nothing
239 
240 private:
242  MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
244  MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
245 
247 
250  bool AddChunk(size_t capacity) {
251  if (!baseAllocator_)
253  if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
254  chunk->capacity = capacity;
255  chunk->size = 0;
256  chunk->next = chunkHead_;
257  chunkHead_ = chunk;
258  return true;
259  }
260  else
261  return false;
262  }
263 
265 
267 
269  struct ChunkHeader {
270  size_t capacity;
271  size_t size;
273  };
274 
277  void *userBuffer_;
278  BaseAllocator* baseAllocator_;
279  BaseAllocator* ownBaseAllocator_;
280 };
281 
283 
284 #endif // CEREAL_RAPIDJSON_ENCODINGS_H_
#define CEREAL_RAPIDJSON_ASSERT(x)
Definition: json.hpp:50
C-runtime library allocator.
Definition: allocators.h:75
static void Free(void *ptr)
Definition: allocators.h:92
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Definition: allocators.h:84
static const bool kNeedFree
Definition: allocators.h:77
void * Malloc(size_t size)
Definition: allocators.h:78
Default memory allocator used by the parser and DOM.
Definition: allocators.h:115
void * Malloc(size_t size)
Allocates a memory block. (concept Allocator)
Definition: allocators.h:189
MemoryPoolAllocator & operator=(const MemoryPoolAllocator &rhs)
Copy assignment operator is not permitted.
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with user-supplied buffer.
Definition: allocators.h:138
BaseAllocator * ownBaseAllocator_
base allocator created by this object.
Definition: allocators.h:279
bool AddChunk(size_t capacity)
Creates a new chunk.
Definition: allocators.h:250
size_t Capacity() const
Computes the total capacity of allocated memory chunks.
Definition: allocators.h:171
ChunkHeader * chunkHead_
Head of the chunk linked-list. Only the head chunk serves allocation.
Definition: allocators.h:275
void Clear()
Deallocates all memory chunks, excluding the user-supplied buffer.
Definition: allocators.h:158
BaseAllocator * baseAllocator_
base allocator for allocating memory chunks.
Definition: allocators.h:278
size_t chunk_capacity_
The minimum capacity of chunk when they are allocated.
Definition: allocators.h:276
static void Free(void *ptr)
Frees a memory block (concept Allocator)
Definition: allocators.h:238
MemoryPoolAllocator(const MemoryPoolAllocator &rhs)
Copy constructor is not permitted.
void * userBuffer_
User supplied buffer.
Definition: allocators.h:277
static const int kDefaultChunkCapacity
Default chunk capacity.
Definition: allocators.h:264
static const bool kNeedFree
Tell users that no need to call Free() with this allocator. (concept Allocator)
Definition: allocators.h:117
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Resizes a memory block (concept Allocator)
Definition: allocators.h:204
~MemoryPoolAllocator()
Destructor.
Definition: allocators.h:152
size_t Size() const
Computes the memory blocks allocated.
Definition: allocators.h:181
MemoryPoolAllocator(size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with chunkSize.
Definition: allocators.h:123
#define CEREAL_RAPIDJSON_ALIGN(x)
Data alignment of the machine.
Definition: rapidjson.h:276
#define CEREAL_RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
#define CEREAL_RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
#define CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
User-defined kDefaultChunkCapacity definition.
Definition: allocators.h:64
common definitions and configuration
#define CEREAL_RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:631
#define CEREAL_RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:627
Chunk header for perpending to each chunk.
Definition: allocators.h:269
ChunkHeader * next
Next chunk in the linked list.
Definition: allocators.h:272
size_t size
Current size of allocated memory in bytes.
Definition: allocators.h:271
size_t capacity
Capacity of the chunk in bytes (excluding the header itself).
Definition: allocators.h:270