11 template <
class TAuxMemoryManager>
15 _auxiliary(auxiliary),
26 template <
class TAuxMemoryManager>
30 _auxiliary(auxiliary),
38 reset(buffer, capacity);
41 template <
class TAuxMemoryManager>
44 assert((size > 0) &&
"Allocated block size must be greater than zero!");
50 void* result = _auxiliary.malloc(size, alignment);
51 if (result !=
nullptr)
61 FreeBlock* prev_free_block =
nullptr;
62 FreeBlock* current_free_block = _free_block;
64 while ((current_free_block !=
nullptr) || allocate)
67 if ((current_free_block ==
nullptr) && allocate)
69 if ((_current !=
nullptr) && (_current->next !=
nullptr))
72 _current = _current->next;
75 current_free_block = (FreeBlock*)_current->buffer;
76 current_free_block->size = _page;
77 current_free_block->next =
nullptr;
80 if (prev_free_block !=
nullptr)
81 prev_free_block->next = current_free_block;
83 _free_block = current_free_block;
91 Page* current = AllocateMemoryPool(_page, _current);
92 if (current !=
nullptr)
98 current_free_block = (FreeBlock*)_current->buffer;
99 current_free_block->size = _page;
100 current_free_block->next =
nullptr;
103 if (prev_free_block !=
nullptr)
104 prev_free_block->next = current_free_block;
106 _free_block = current_free_block;
123 size_t adjustment = AlignAdjustment(current_free_block, alignment,
sizeof(AllocBlock));
126 size_t aligned_size = size + adjustment;
129 while (current_free_block->next !=
nullptr)
131 FreeBlock* base_free_block = current_free_block;
132 FreeBlock* next_free_block = current_free_block->next;
135 if (((uint8_t*)base_free_block + base_free_block->size) == (uint8_t*)next_free_block)
137 current_free_block->size += next_free_block->size;
138 current_free_block->next = next_free_block->next;
145 if (current_free_block->size < aligned_size)
148 if (current_free_block->next !=
nullptr)
149 prev_free_block = current_free_block;
150 current_free_block = current_free_block->next;
154 static_assert(
sizeof(AllocBlock) >=
sizeof(FreeBlock),
"Allocated block structure size must not be less than free block structure size!");
157 if ((current_free_block->size - aligned_size) <=
sizeof(AllocBlock))
160 aligned_size = current_free_block->size;
163 if (prev_free_block !=
nullptr)
164 prev_free_block->next = current_free_block->next;
166 _free_block = current_free_block->next;
171 FreeBlock* next_free_block = (FreeBlock*)((uint8_t*)current_free_block + aligned_size);
172 next_free_block->size = current_free_block->size - aligned_size;
173 next_free_block->next = current_free_block->next;
176 if (prev_free_block !=
nullptr)
177 prev_free_block->next = next_free_block;
179 _free_block = next_free_block;
183 uint8_t* aligned = (uint8_t*)current_free_block + adjustment;
186 AllocBlock* alloc_block = (AllocBlock*)(aligned -
sizeof(AllocBlock));
187 alloc_block->size = aligned_size;
188 alloc_block->adjustment = adjustment;
201 template <
class TAuxMemoryManager>
204 assert((ptr !=
nullptr) &&
"Deallocated block must be valid!");
209 _auxiliary.free(ptr, size);
218 AllocBlock* alloc_block = (AllocBlock*)((uint8_t*)ptr -
sizeof(AllocBlock));
220 uint8_t* block_start = (uint8_t*)ptr - alloc_block->adjustment;
221 size_t block_size = alloc_block->size;
222 uint8_t* block_end = block_start + block_size;
225 FreeBlock* old_free_block = _free_block;
226 FreeBlock* new_free_block = (FreeBlock*)block_start;
227 new_free_block->size = block_size;
228 new_free_block->next = old_free_block;
229 _free_block = new_free_block;
232 if (old_free_block !=
nullptr)
235 if (((uint8_t*)old_free_block + old_free_block->size) == block_start)
237 old_free_block->size += new_free_block->size;
238 _free_block = old_free_block;
241 else if ((uint8_t*)old_free_block == block_end)
243 new_free_block->size += old_free_block->size;
244 new_free_block->next = old_free_block->next;
245 _free_block = new_free_block;
254 template <
class TAuxMemoryManager>
257 assert((_allocated == 0) &&
"Memory leak detected! Allocated memory size must be zero!");
258 assert((_allocations == 0) &&
"Memory leak detected! Count of active memory allocations must be zero!");
260 if (_current !=
nullptr)
263 while (_current->prev !=
nullptr)
264 _current = _current->prev;
267 _free_block = (FreeBlock*)_current->buffer;
268 _free_block->size = _page;
269 _free_block->next =
nullptr;
273 template <
class TAuxMemoryManager>
276 assert((page >= (
sizeof(Page) +
sizeof(AllocBlock))) &&
"Memory pool page must be big enough to fit at least one allocation block!");
278 assert((_allocated == 0) &&
"Memory leak detected! Allocated memory size must be zero!");
279 assert((_allocations == 0) &&
"Memory leak detected! Count of active memory allocations must be zero!");
286 _max_pages = (pages > 0) ? pages : std::numeric_limits<size_t>::max();
291 Page* current = AllocateMemoryPool(page, _current);
292 if (current !=
nullptr)
298 _free_block = (FreeBlock*)_current->buffer;
299 _free_block->size = page;
300 _free_block->next =
nullptr;
307 template <
class TAuxMemoryManager>
310 assert((buffer !=
nullptr) &&
"Memory pool buffer must be valid!");
311 assert((capacity >= (
sizeof(Page) +
sizeof(AllocBlock))) &&
"Memory pool buffer capacity must be big enough to fit at least one allocation block!");
313 assert((_allocated == 0) &&
"Memory leak detected! Allocated memory size must be zero!");
314 assert((_allocations == 0) &&
"Memory leak detected! Count of active memory allocations must be zero!");
324 _current = (Page*)buffer;
325 _current->buffer = (uint8_t*)buffer +
sizeof(Page);
326 _current->prev =
nullptr;
327 _current->next =
nullptr;
330 _free_block = (FreeBlock*)_current->buffer;
331 _free_block->size = capacity -
sizeof(Page);
332 _free_block->next =
nullptr;
335 template <
class TAuxMemoryManager>
338 assert((_allocated == 0) &&
"Memory leak detected! Allocated memory size must be zero!");
339 assert((_allocations == 0) &&
"Memory leak detected! Count of active memory allocations must be zero!");
352 _free_block =
nullptr;
355 template <
class TAuxMemoryManager>
358 return (uint8_t*)
Memory::Align(address, alignment) - (uint8_t*)address;
361 template <
class TAuxMemoryManager>
362 inline size_t PoolMemoryManager<TAuxMemoryManager>::AlignAdjustment(
const void* address,
size_t alignment,
size_t header)
364 size_t adjustment = AlignAdjustment(address, alignment);
366 size_t required = header;
367 if (adjustment < required)
369 required -= adjustment;
370 adjustment += alignment * (required / alignment);
371 if ((required % alignment) > 0)
372 adjustment += alignment;
378 template <
class TAuxMemoryManager>
379 inline typename PoolMemoryManager<TAuxMemoryManager>::Page* PoolMemoryManager<TAuxMemoryManager>::AllocateMemoryPool(
size_t capacity, Page* prev)
382 uint8_t* buffer = (uint8_t*)_auxiliary.malloc(
sizeof(Page) + capacity +
alignof(std::max_align_t));
383 Page* page = (Page*)buffer;
387 page->buffer = buffer +
sizeof(Page);
389 page->next =
nullptr;
399 template <
class TAuxMemoryManager>
400 inline void PoolMemoryManager<TAuxMemoryManager>::ClearMemoryPool()
405 while (_current !=
nullptr)
407 Page* prev = _current->prev;
408 Page* next = _current->next;
409 _auxiliary.free(_current,
sizeof(Page) + _page +
alignof(std::max_align_t));
415 else if (next !=
nullptr)
425 _free_block =
nullptr;
static bool IsValidAlignment(size_t alignment) noexcept
Is the given alignment valid?
static T * Align(const T *address, size_t alignment=alignof(T), bool upwards=true) noexcept
Align pointer (upwards or downwards)
Memory pool manager class.
size_t pages() const noexcept
Max pages size.
void reset()
Reset the memory manager.
PoolMemoryManager(TAuxMemoryManager &auxiliary)
Initialize memory pool manager with an auxiliary memory manager.
void * malloc(size_t size, size_t alignment=alignof(std::max_align_t))
Allocate a new memory block of the given size.
void clear()
Clear memory pool.
size_t page() const noexcept
Page size in bytes.
void free(void *ptr, size_t size)
Free the previously allocated memory block.
C++ Common project definitions.