RetroArch
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 
55 // CrtAllocator
57 
59 
62 class CrtAllocator {
63 public:
64  static const bool kNeedFree = true;
65  void* Malloc(size_t size) {
66  if (size) // behavior of malloc(0) is implementation defined.
67  return std::malloc(size);
68  else
69  return NULL; // standardize to returning NULL.
70  }
71  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
72  (void)originalSize;
73  if (newSize == 0) {
74  std::free(originalPtr);
75  return NULL;
76  }
77  return std::realloc(originalPtr, newSize);
78  }
79  static void Free(void *ptr) { std::free(ptr); }
80 };
81 
83 // MemoryPoolAllocator
84 
86 
101 template <typename BaseAllocator = CrtAllocator>
103 public:
104  static const bool kNeedFree = false;
105 
107 
110  MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
111  chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
112  {
113  }
114 
116 
125  MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
126  chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
127  {
128  RAPIDJSON_ASSERT(buffer != 0);
129  RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
130  chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
131  chunkHead_->capacity = size - sizeof(ChunkHeader);
132  chunkHead_->size = 0;
133  chunkHead_->next = 0;
134  }
135 
137 
140  Clear();
142  }
143 
145  void Clear() {
146  while (chunkHead_ && chunkHead_ != userBuffer_) {
147  ChunkHeader* next = chunkHead_->next;
148  baseAllocator_->Free(chunkHead_);
149  chunkHead_ = next;
150  }
152  chunkHead_->size = 0; // Clear user buffer
153  }
154 
156 
158  size_t Capacity() const {
159  size_t capacity = 0;
160  for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
161  capacity += c->capacity;
162  return capacity;
163  }
164 
166 
168  size_t Size() const {
169  size_t size = 0;
170  for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
171  size += c->size;
172  return size;
173  }
174 
176  void* Malloc(size_t size) {
177  if (!size)
178  return NULL;
179 
181  if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
183  return NULL;
184 
185  void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
186  chunkHead_->size += size;
187  return buffer;
188  }
189 
191  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
192  if (originalPtr == 0)
193  return Malloc(newSize);
194 
195  if (newSize == 0)
196  return NULL;
197 
198  originalSize = RAPIDJSON_ALIGN(originalSize);
199  newSize = RAPIDJSON_ALIGN(newSize);
200 
201  // Do not shrink if new size is smaller than original
202  if (originalSize >= newSize)
203  return originalPtr;
204 
205  // Simply expand it if it is the last allocation and there is sufficient space
206  if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
207  size_t increment = static_cast<size_t>(newSize - originalSize);
208  if (chunkHead_->size + increment <= chunkHead_->capacity) {
209  chunkHead_->size += increment;
210  return originalPtr;
211  }
212  }
213 
214  // Realloc process: allocate and copy memory, do not free original buffer.
215  if (void* newBuffer = Malloc(newSize)) {
216  if (originalSize)
217  std::memcpy(newBuffer, originalPtr, originalSize);
218  return newBuffer;
219  }
220  else
221  return NULL;
222  }
223 
225  static void Free(void *ptr) { (void)ptr; } // Do nothing
226 
227 private:
229  MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
231  MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
232 
234 
237  bool AddChunk(size_t capacity) {
238  if (!baseAllocator_)
239  ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
240  if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
241  chunk->capacity = capacity;
242  chunk->size = 0;
243  chunk->next = chunkHead_;
244  chunkHead_ = chunk;
245  return true;
246  }
247  else
248  return false;
249  }
250 
251  static const int kDefaultChunkCapacity = 64 * 1024;
252 
254 
256  struct ChunkHeader {
257  size_t capacity;
258  size_t size;
260  };
261 
262  ChunkHeader *chunkHead_;
264  void *userBuffer_;
265  BaseAllocator* baseAllocator_;
266  BaseAllocator* ownBaseAllocator_;
267 };
268 
270 
271 #endif // RAPIDJSON_ENCODINGS_H_
const GLvoid * ptr
Definition: nx_glsym.h:242
size_t chunk_capacity_
The minimum capacity of chunk when they are allocated.
Definition: allocators.h:263
static void Free(void *ptr)
Frees a memory block (concept Allocator)
Definition: allocators.h:225
Default memory allocator used by the parser and DOM.
Definition: allocators.h:102
common definitions and configuration
BaseAllocator * baseAllocator_
base allocator for allocating memory chunks.
Definition: allocators.h:265
GLuint buffer
Definition: glext.h:6555
static const bool kNeedFree
Tell users that no need to call Free() with this allocator. (concept Allocator)
Definition: allocators.h:104
#define RAPIDJSON_NEW(x)
! customization point for global new
Definition: rapidjson.h:586
void * malloc(YYSIZE_T)
GLsizeiptr size
Definition: glext.h:6559
C-runtime library allocator.
Definition: allocators.h:62
size_t size
Current size of allocated memory in bytes.
Definition: allocators.h:258
#define RAPIDJSON_ALIGN(x)
Data alignment of the machine.
Definition: rapidjson.h:275
ChunkHeader * chunkHead_
Head of the chunk linked-list. Only the head chunk serves allocation.
Definition: allocators.h:262
#define next(ls)
Definition: llex.c:32
typedef void(__stdcall *PFN_DESTRUCTION_CALLBACK)(void *pData)
size_t Size() const
Computes the memory blocks allocated.
Definition: allocators.h:168
~MemoryPoolAllocator()
Destructor.
Definition: allocators.h:139
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:119
const GLubyte * c
Definition: glext.h:9812
static const int kDefaultChunkCapacity
Default chunk capacity.
Definition: allocators.h:251
Chunk header for perpending to each chunk.
Definition: allocators.h:256
ChunkHeader * next
Next chunk in the linked list.
Definition: allocators.h:259
void * Malloc(size_t size)
Allocates a memory block. (concept Allocator)
Definition: allocators.h:176
MemoryPoolAllocator & operator=(const MemoryPoolAllocator &rhs)
Copy assignment operator is not permitted.
#define NULL
Pointer to 0.
Definition: gctypes.h:65
MemoryPoolAllocator(size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with chunkSize.
Definition: allocators.h:110
static const bool kNeedFree
Definition: allocators.h:64
BaseAllocator * ownBaseAllocator_
base allocator created by this object.
Definition: allocators.h:266
void * Malloc(size_t size)
Definition: allocators.h:65
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Definition: allocators.h:71
size_t Capacity() const
Computes the total capacity of allocated memory chunks.
Definition: allocators.h:158
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:402
bool AddChunk(size_t capacity)
Creates a new chunk.
Definition: allocators.h:237
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:590
static void Free(void *ptr)
Definition: allocators.h:79
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:116
void free(void *)
void * userBuffer_
User supplied buffer.
Definition: allocators.h:264
void Clear()
Deallocates all memory chunks, excluding the user-supplied buffer.
Definition: allocators.h:145
Definition: video4linux2.c:51
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with user-supplied buffer.
Definition: allocators.h:125
size_t capacity
Capacity of the chunk in bytes (excluding the header itself).
Definition: allocators.h:257
void * memcpy(void *dst, const void *src, size_t len)
Definition: string.c:26
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Resizes a memory block (concept Allocator)
Definition: allocators.h:191