bubel-ecs/source/bubel/ecs/block_allocator.d
Mergul 6929f5a748 Mostly bugfix update + empty components support and remove EntityID from Event structure
-empty components now take no memory, so flag components is now far better
-added test for critical bug
-fixed critical bug with adding/removing entities form inside events
-fixed small bug with TestRunner
-improve basic tests
-fixed betterC compilation on DMD
-remove EntityID form Event structure
-added "return" attribute to some functions
-moved some code from Tempalte side to actual implementation
-fixed bug with EntityTemplate copying
-commented out some possibliy unused code
-use code formatter
2020-05-27 17:03:44 +02:00

99 lines
3.3 KiB
D

/************************************************************************************************************************
It's internal code.
Module contain memory allocator.
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.block_allocator;
import bubel.ecs.manager;
import bubel.ecs.std;
/************************************************************************************************************************
Allocator allocate large blocks and return smaller blocks. When there is no more blocks then next large block is allocated.
By default freeing memory only returns it to allocator. To free large memory chunks freeMemory function is used.
freeMemory function return to system memory even if chunk blocks wasn't freed.
*/
struct BlockAllocator
{
/************************************************************************************************************************
Get new block. Allocator automatically allocate next memory chunk if needed.
*/
void* getBlock() nothrow @nogc
{
if (next_block is null)
allocBlock();
void* ret = next_block;
next_block = *cast(void**) next_block;
return ret;
}
/************************************************************************************************************************
Return block to allocator for further use.
*/
void freeBlock(void* block) nothrow @nogc
{
*cast(void**) block = next_block;
next_block = block;
}
/************************************************************************************************************************
Free whole used memory. This function return to system all memory chunks even if not every black was freed.
*/
void freeMemory() nothrow @nogc
{
while (pointers)
{
foreach (i; 0 .. pointers.numberof)
{
Mallocator.alignDispose(pointers.blocks[i]);
}
BlockPointers* next_pointers = pointers.next_pointers;
Mallocator.dispose(pointers);
pointers = next_pointers;
}
}
private:
void allocBlock() nothrow @nogc
{
next_block = cast(void*) Mallocator.alignAlloc(block_size * blocks_in_allocation,
block_size);
if (next_block is null)
assert(0);
if (pointers is null)
pointers = Mallocator.make!BlockPointers;
if (pointers.numberof >= 32)
{
BlockPointers* new_pointers = Mallocator.make!BlockPointers;
new_pointers.next_pointers = pointers;
pointers = new_pointers;
}
pointers.blocks[pointers.numberof++] = next_block;
foreach (i; 0 .. blocks_in_allocation - 1)
{
void** pointer = cast(void**)(next_block + i * block_size);
*pointer = next_block + (i + 1) * block_size;
}
void** pointer = cast(void**)(next_block + (blocks_in_allocation - 1) * block_size);
*pointer = null;
}
struct BlockPointers
{
void*[32] blocks;
uint numberof = 0;
BlockPointers* next_pointers = null;
}
uint block_size;
uint blocks_in_allocation;
void* next_block = null;
BlockPointers* pointers = null;
}