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
51 void operator=(ArenaAllocator&& rhs);
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 {
172 }
173 if (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 // pad up to next multiple of 16 to avoid alignment issues
190 constexpr size_t alignedSize = (sizeof(T) + 15) & ~size_t(15);
191 if constexpr (alignedSize > ChunkSize)
192 {
193 // allocate block and retire it directly
194 byte* block = (byte*)Memory::Alloc(ObjectArrayHeap, sizeof(T));
195 this->retiredChunks.Append(block);
196 ret = new (block) T;
197 }
198 else
199 {
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 size_t 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 // pad up to next multiple of 16 to avoid alignment issues
228 size_t alignedSize = Memory::align(sizeof(T) * num, 16ull);
229 if (alignedSize > ChunkSize)
230 {
231 // the whole range doesn't fit into a chunk, allocate block and retire it directly
232 byte* block = (byte*)Memory::Alloc(ObjectArrayHeap, sizeof(T) * num);
233 this->retiredChunks.Append(block);
234 ret = new (block) T[num];
235 }
236 else
237 {
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 size_t 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 // pad to next alignment.
266 SizeT alignedSize = Memory::align(size, 16);
267 if (alignedSize > ChunkSize)
268 {
269 // allocate block and retire it directly
270 byte* block = (byte*)Memory::Alloc(ObjectArrayHeap, size);
271 this->retiredChunks.Append(block);
272 ret = block;
273 }
274 else
275 {
276 size = alignedSize;
277 if (this->iterator == nullptr)
278 {
279 this->NewChunk();
280 }
281 else
282 {
283 PtrDiff remainder = this->currentChunk + ChunkSize - this->iterator;
284 if (remainder < size)
285 this->NewChunk();
286 }
287 ret = this->iterator;
288 this->iterator += size;
289 }
290
291 return ret;
292}
293
294} // namespace Memory
~ArenaAllocator()
destructor
Definition arenaallocator.h:87
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
void operator=(const ArenaAllocator &rhs)
assignment operator
Definition arenaallocator.h:142
byte * currentChunk
Definition arenaallocator.h:65
Util::Array< byte * > retiredChunks
Definition arenaallocator.h:67
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:61
#define n_assert(exp)
Definition debug.h:58
Nebula compiler specific defines and configuration.
Definition arenaallocator.h:31
__forceinline unsigned int align(unsigned int alignant, unsigned int alignment)
Definition memory.h:21
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:46
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41