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 RAPIDJSON_ALLOCATORS_H_
16 #define RAPIDJSON_ALLOCATORS_H_
17 
18 #include "rapidjson.h"
19 
21 
23 // Allocator
24 
63 #ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
64 #define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
65 #endif
66 
68 // CrtAllocator
69 
71 
75 {
76 public:
77  static const bool kNeedFree = true;
78  void* Malloc(size_t size)
79  {
80  if (size) // behavior of malloc(0) is implementation defined.
81  return std::malloc(size);
82  else
83  return NULL; // standardize to returning NULL.
84  }
85  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
86  {
87  (void)originalSize;
88  if (newSize == 0)
89  {
90  std::free(originalPtr);
91  return NULL;
92  }
93  return std::realloc(originalPtr, newSize);
94  }
95  static void Free(void* ptr)
96  {
97  std::free(ptr);
98  }
99 };
100 
102 // MemoryPoolAllocator
103 
105 
120 template <typename BaseAllocator = CrtAllocator>
122 {
123 public:
124  static const bool kNeedFree =
125  false;
126 
128 
131  MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0)
132  : chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
133  {
134  }
135 
137 
146  MemoryPoolAllocator(void* buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity,
147  BaseAllocator* baseAllocator = 0)
148  : chunkHead_(0)
149  , chunk_capacity_(chunkSize)
150  , userBuffer_(buffer)
151  , baseAllocator_(baseAllocator)
152  , ownBaseAllocator_(0)
153  {
154  RAPIDJSON_ASSERT(buffer != 0);
155  RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
156  chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
157  chunkHead_->capacity = size - sizeof(ChunkHeader);
158  chunkHead_->size = 0;
159  chunkHead_->next = 0;
160  }
161 
163 
166  {
167  Clear();
168  RAPIDJSON_DELETE(ownBaseAllocator_);
169  }
170 
172  void Clear()
173  {
174  while (chunkHead_ && chunkHead_ != userBuffer_)
175  {
176  ChunkHeader* next = chunkHead_->next;
177  baseAllocator_->Free(chunkHead_);
178  chunkHead_ = next;
179  }
180  if (chunkHead_ && chunkHead_ == userBuffer_)
181  chunkHead_->size = 0; // Clear user buffer
182  }
183 
185 
187  size_t Capacity() const
188  {
189  size_t capacity = 0;
190  for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
191  capacity += c->capacity;
192  return capacity;
193  }
194 
196 
198  size_t Size() const
199  {
200  size_t size = 0;
201  for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
202  size += c->size;
203  return size;
204  }
205 
207  void* Malloc(size_t size)
208  {
209  if (!size)
210  return NULL;
211 
212  size = RAPIDJSON_ALIGN(size);
213  if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
214  if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
215  return NULL;
216 
217  void* buffer = reinterpret_cast<char*>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
218  chunkHead_->size += size;
219  return buffer;
220  }
221 
223  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
224  {
225  if (originalPtr == 0)
226  return Malloc(newSize);
227 
228  if (newSize == 0)
229  return NULL;
230 
231  originalSize = RAPIDJSON_ALIGN(originalSize);
232  newSize = RAPIDJSON_ALIGN(newSize);
233 
234  // Do not shrink if new size is smaller than original
235  if (originalSize >= newSize)
236  return originalPtr;
237 
238  // Simply expand it if it is the last allocation and there is sufficient space
239  if (originalPtr ==
240  reinterpret_cast<char*>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize)
241  {
242  size_t increment = static_cast<size_t>(newSize - originalSize);
243  if (chunkHead_->size + increment <= chunkHead_->capacity)
244  {
245  chunkHead_->size += increment;
246  return originalPtr;
247  }
248  }
249 
250  // Realloc process: allocate and copy memory, do not free original buffer.
251  if (void* newBuffer = Malloc(newSize))
252  {
253  if (originalSize)
254  std::memcpy(newBuffer, originalPtr, originalSize);
255  return newBuffer;
256  }
257  else
258  return NULL;
259  }
260 
262  static void Free(void* ptr)
263  {
264  (void)ptr;
265  } // Do nothing
266 
267 private:
269  MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
271  MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
272 
274 
277  bool AddChunk(size_t capacity)
278  {
279  if (!baseAllocator_)
280  ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
281  if (ChunkHeader* chunk =
282  reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity)))
283  {
284  chunk->capacity = capacity;
285  chunk->size = 0;
286  chunk->next = chunkHead_;
287  chunkHead_ = chunk;
288  return true;
289  }
290  else
291  return false;
292  }
293 
294  static const int kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY;
295 
297 
299  struct ChunkHeader
300  {
301  size_t capacity;
302  size_t size;
304  };
305 
308  void* userBuffer_;
309  BaseAllocator* baseAllocator_;
310  BaseAllocator* ownBaseAllocator_;
311 };
312 
314 
315 #endif // RAPIDJSON_ENCODINGS_H_
size_t Capacity() const
Computes the total capacity of allocated memory chunks.
Definition: allocators.h:187
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
User-defined kDefaultChunkCapacity definition.
Definition: allocators.h:64
BaseAllocator * ownBaseAllocator_
base allocator created by this object.
Definition: allocators.h:310
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:416
void * Malloc(size_t size)
Allocates a memory block. (concept Allocator)
Definition: allocators.h:207
void * userBuffer_
User supplied buffer.
Definition: allocators.h:308
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:126
void * Malloc(size_t size)
Definition: allocators.h:78
size_t Size() const
Computes the memory blocks allocated.
Definition: allocators.h:198
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
void Clear()
Deallocates all memory chunks, excluding the user-supplied buffer.
Definition: allocators.h:172
Chunk header for perpending to each chunk.
Definition: allocators.h:299
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:649
bool AddChunk(size_t capacity)
Creates a new chunk.
Definition: allocators.h:277
ChunkHeader * chunkHead_
Head of the chunk linked-list. Only the head chunk serves allocation.
Definition: allocators.h:306
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Definition: allocators.h:85
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:653
BaseAllocator * baseAllocator_
base allocator for allocating memory chunks.
Definition: allocators.h:309
size_t size
Current size of allocated memory in bytes.
Definition: allocators.h:302
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Resizes a memory block (concept Allocator)
Definition: allocators.h:223
C-runtime library allocator.
Definition: allocators.h:74
size_t capacity
Capacity of the chunk in bytes (excluding the header itself).
Definition: allocators.h:301
common definitions and configuration
static void Free(void *ptr)
Definition: allocators.h:95
size_t chunk_capacity_
The minimum capacity of chunk when they are allocated.
Definition: allocators.h:307
static void Free(void *ptr)
Frees a memory block (concept Allocator)
Definition: allocators.h:262
static const bool kNeedFree
Definition: allocators.h:77
ChunkHeader * next
Next chunk in the linked list.
Definition: allocators.h:303
#define RAPIDJSON_ALIGN(x)
Data alignment of the machine.
Definition: rapidjson.h:281
MemoryPoolAllocator(size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with chunkSize.
Definition: allocators.h:131
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with user-supplied buffer.
Definition: allocators.h:146
Default memory allocator used by the parser and DOM.
Definition: allocators.h:121
~MemoryPoolAllocator()
Destructor.
Definition: allocators.h:165


xbot_talker
Author(s): wangxiaoyun
autogenerated on Sat Oct 10 2020 03:27:53