Nebula
Loading...
Searching...
No Matches
arenaallocator.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
22//------------------------------------------------------------------------------
23#include "core/config.h"
24#include "math/scalar.h"
25#include "util/array.h"
26
27#define SMALL_CHUNK 0x100
28#define MEDIUM_CHUNK 0x1000
29#define BIG_CHUNK 0x10000
30namespace Memory
31{
32
33
34template <int ChunkSize>
36{
37public:
42
46 void operator=(const ArenaAllocator& rhs);
47
52
54 template <typename T> T* Alloc();
56 template <typename T> T* Alloc(SizeT num);
58 void* Alloc(SizeT size);
60 void NewChunk();
62 void Release();
63
64private:
66 byte* iterator;
68};
69
70//------------------------------------------------------------------------------
73template <int ChunkSize>
74inline
76 currentChunk(nullptr),
77 iterator(nullptr)
78{
79 // constructor
80}
81
82//------------------------------------------------------------------------------
85template <int ChunkSize>
86inline
88{
89 this->Release(); // perhaps call release when we actually want to dealloc
90}
91
92//------------------------------------------------------------------------------
95template<int ChunkSize>
96inline
98{
99 this->retiredChunks = rhs.retiredChunks;
100 this->currentChunk = rhs.currentChunk;
101 this->iterator = rhs.iterator;
102
103 rhs.retiredChunks.Clear();
104 rhs.currentChunk = nullptr;
105 rhs.iterator = nullptr;
106}
107
108//------------------------------------------------------------------------------
111template<int ChunkSize>
112inline
114{
115 // copy chunk
116 this->retiredChunks = rhs.retiredChunks;
117 this->currentChunk = rhs.currentChunk;
118 this->iterator = rhs.iterator;
119}
120
121//------------------------------------------------------------------------------
124template<int ChunkSize>
125inline void
127{
128 this->retiredChunks = rhs.retiredChunks;
129 this->currentChunk = rhs.currentChunk;
130 this->iterator = rhs.iterator;
131
132 rhs.retiredChunks.Clear();
133 rhs.currentChunk = nullptr;
134 rhs.iterator = nullptr;
135}
136
137//------------------------------------------------------------------------------
140template<int ChunkSize>
141inline void
143{
144 this->retiredChunks = rhs.retiredChunks;
145 this->currentChunk = rhs.currentChunk;
146 this->iterator = rhs.iterator;
147}
148
149//------------------------------------------------------------------------------
152template <int ChunkSize>
153inline void
155{
156 if (this->currentChunk != nullptr)
157 this->retiredChunks.Append(this->currentChunk);
158 this->currentChunk = (byte*)Memory::Alloc(ObjectArrayHeap, ChunkSize);
159 this->iterator = this->currentChunk;
160}
161
162//------------------------------------------------------------------------------
165template<int ChunkSize>
167{
168 IndexT i;
169 for (i = 0; i < this->retiredChunks.Size(); i++)
170 {
171 Memory::Free(ObjectArrayHeap, this->retiredChunks[i]);
172 }
173 if (this->currentChunk)
174 Memory::Free(ObjectArrayHeap, this->currentChunk);
175 this->retiredChunks.Clear();
176 this->currentChunk = nullptr;
177 this->iterator = nullptr;
178}
179
180//------------------------------------------------------------------------------
183template <int ChunkSize>
184template<typename T>
185inline T*
187{
188 T* ret = nullptr;
189 if constexpr (sizeof(T) > ChunkSize)
190 {
191 // allocate block and retire it directly
192 byte* block = (byte*)Memory::Alloc(ObjectArrayHeap, sizeof(T));
193 this->retiredChunks.Append(block);
194 ret = new (block) T;
195 }
196 else
197 {
198 // pad up to next multiple of 16 to avoid alignment issues
199 SizeT alignedSize = Math::align(sizeof(T), 16);
200 if (this->iterator == nullptr)
201 {
202 this->NewChunk();
203 }
204 else
205 {
206 // we cast the pointer diff but it should be safe since it should never be above ChunkSize
207 SizeT remainder = ChunkSize - SizeT(this->iterator - this->currentChunk);
208 if (remainder < alignedSize)
209 this->NewChunk();
210 }
211
212 ret = new (this->iterator) T;
213 this->iterator += alignedSize;
214 }
215 return ret;
216}
217
218//------------------------------------------------------------------------------
221template <int ChunkSize>
222template<typename T>
223inline T*
225{
226 T* ret = nullptr;
227 if constexpr (sizeof(T) > ChunkSize)
228 {
229 // allocate block and retire it directly
230 byte* block = (byte*)Memory::Alloc(ObjectArrayHeap, sizeof(T) * num);
231 this->retiredChunks.Append(block);
232 ret = new (block) T[num];
233 }
234 else
235 {
236 // pad up to next multiple of 16 to avoid alignment issues
237 SizeT alignedSize = Math::align(sizeof(T) * num, 16);
238 if (this->iterator == nullptr)
239 {
240 this->NewChunk();
241 }
242 else
243 {
244 // we cast the pointer diff but it should be safe since it should never be above ChunkSize
245 SizeT remainder = ChunkSize - SizeT(this->iterator - this->currentChunk);
246 if (remainder < alignedSize)
247 this->NewChunk();
248 }
249
250 ret = new (this->iterator) T[num];
251 this->iterator += alignedSize;
252 }
253 return ret;
254}
255
256//------------------------------------------------------------------------------
259template <int ChunkSize>
260inline void*
262{
263 n_assert(size != 0);
264 void* ret = nullptr;
265 if (size > ChunkSize)
266 {
267 // allocate block and retire it directly
268 byte* block = (byte*)Memory::Alloc(ObjectArrayHeap, size);
269 this->retiredChunks.Append(block);
270 ret = block;
271 }
272 else
273 {
274 // pad to next alignment.
275 size = Math::align(size, 16);
276 if (this->iterator == nullptr)
277 {
278 this->NewChunk();
279 }
280 else
281 {
282 PtrDiff remainder = this->currentChunk + ChunkSize - this->iterator;
283 if (remainder < size)
284 this->NewChunk();
285 }
286 ret = this->iterator;
287 this->iterator += size;
288 }
289
290 return ret;
291}
292
293} // namespace Memory
Allocates memory in chunks.
Definition arenaallocator.h:36
~ArenaAllocator()
destructor
Definition arenaallocator.h:87
void * Alloc(SizeT size)
allocate new chunk of size
Definition arenaallocator.h:261
T * Alloc()
allocate new object, and calls constructor, but beware because this allocator does not run the destru...
Definition arenaallocator.h:186
ArenaAllocator()
constructor
Definition arenaallocator.h:75
ArenaAllocator(ArenaAllocator &&rhs)
move constructor
Definition arenaallocator.h:97
ArenaAllocator(const ArenaAllocator &rhs)
copy constructor
Definition arenaallocator.h:113
void operator=(const ArenaAllocator &rhs)
assignment operator
Definition arenaallocator.h:142
byte * currentChunk
Definition arenaallocator.h:65
void operator=(ArenaAllocator &&rhs)
move operator
Definition arenaallocator.h:126
Util::Array< byte * > retiredChunks
Definition arenaallocator.h:67
T * Alloc(SizeT num)
Allocate several new objects of a specific type.
Definition arenaallocator.h:224
byte * iterator
Definition arenaallocator.h:66
void Release()
release all memory
Definition arenaallocator.h:166
void NewChunk()
retires a chunk and creates a new one (might waste memory)
Definition arenaallocator.h:154
Nebula's dynamic array class.
Definition array.h:60
#define n_assert(exp)
Definition debug.h:50
Nebula compiler specific defines and configuration.
__forceinline unsigned int align(unsigned int alignant, unsigned int alignment)
Definition scalar.h:722
Allocates memory using the TLSF method (http://www.gii.upv.es/tlsf/files/ecrts04_tlsf....
Definition arenaallocator.h:31
void * Alloc(HeapType heapType, size_t size, size_t alignment)
Allocate a block of memory from one of the global heaps.
Definition osxmemory.cc:56
void Free(HeapType heapType, void *ptr)
Free a block of memory.
Definition osxmemory.cc:136
@ ObjectArrayHeap
Definition osxmemoryconfig.h:28
Nebula's scalar datatype.
ptrdiff PtrDiff
Definition types.h:53
int SizeT
Definition types.h:49
int IndexT
Definition types.h:48