module dlib.alloc; import dlib.aliases; import dlib.math; import dlib.platform; import dlib.util; import std.stdio; import core.stdc.string : memset; import core.memory; const DEFAULT_ALIGNMENT = (void *).sizeof * 2; struct ArenaPool { u8* mem; u64 pos; } struct Arena { SLList!(ArenaPool) pools; u64 pool_length; u64 length; }; T* MAlloc(T)() { void* mem = MemAlloc(T.sizeof); return cast(T*)mem; } T[] MAllocArray(T)(u64 count) { void* mem = MemAlloc(T.sizeof * count); return (cast(T*)mem)[0 .. count]; } void MFree(T)(T* ptr) { MemFree(ptr, T.sizeof); } void MFreeArray(T)(T[] slice) { MemFree(slice.ptr, cast(u64)slice.length * T.sizeof); } T* Alloc(T)() { void* mem = pureMalloc(T.sizeof); memset(mem, 0, T.sizeof); return (cast(T*)mem); } T[] AllocArray(T)(u64 count) { void* mem = pureMalloc(T.sizeof * count); memset(mem, 0, T.sizeof * count); return (cast(T*)mem)[0 .. count]; } Arena CreateArena(u64 size) { Arena arena = { length: size, pool_length: size - Node!(ArenaPool).sizeof, }; AddArenaPool(&arena); return arena; }; void AddArenaPool(Arena* arena) { u8* mem = cast(u8*)MemAlloc(arena.length); Node!(ArenaPool)* node = cast(Node!(ArenaPool)*)mem; node.value.mem = (cast(u8*)mem) + Node!(ArenaPool).sizeof; node.value.pos = 0; assert(node.value.mem != null, "Unable to allocate memory for arena"); PushFront(&arena.pools, node, null); } T[] AllocArray(T)(Arena* arena, u64 count) { void* mem = AllocAlign(arena, T.sizeof * count, DEFAULT_ALIGNMENT); memset(mem, 0, T.sizeof * count); return (cast(T*)mem)[0 .. count]; } T* Alloc(T)(Arena* arena) { void* mem = AllocAlign(arena, T.sizeof, DEFAULT_ALIGNMENT); memset(mem, 0, T.sizeof); return cast(T*)mem; }; void* AllocAlign(Arena* arena, u64 size, u64 alignment) { assert(size <= arena.pool_length, "Unable to allocate memory within arena size"); void* ptr = null; uintptr mem_pos, current, offset; Node!(ArenaPool)* node = arena.pools.first; while (true) { if (node == null) { AddArenaPool(arena); node = arena.pools.first; } mem_pos = cast(uintptr)node.value.mem; current = mem_pos + node.value.pos; offset = AlignPow2(current, alignment) - mem_pos; if (offset+size <= arena.pool_length) { break; } node = node.next; } ptr = &node.value.mem[offset]; node.value.pos = offset+size; return ptr; }; void Reset(Arena* arena) { Node!(ArenaPool)* node = arena.pools.first; while (node != null) { node.value.pos = 0; node = node.next; } } void Free(Arena* arena) { Node!(ArenaPool)* node = arena.pools.first; while (node != null) { MemFree(node.value.mem, arena.length); node = node.next; } } void FreeArray(T)(T[] arr) { pureFree(arr.ptr); } void Free(T)(T* ptr) { pureFree(ptr); }