373 lines
5.2 KiB
D
373 lines
5.2 KiB
D
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;
|
|
|
|
static Scratch g_scratch;
|
|
static u64 g_scratch_index;
|
|
|
|
const DEFAULT_ALIGNMENT = (void *).sizeof * 2;
|
|
|
|
struct Scratch
|
|
{
|
|
Arena arena;
|
|
bool init;
|
|
}
|
|
|
|
struct ArenaPool
|
|
{
|
|
u8* mem;
|
|
u64 pos;
|
|
u64 length;
|
|
}
|
|
|
|
struct Arena
|
|
{
|
|
SLList!(ArenaPool) pools;
|
|
u64 def_size;
|
|
}
|
|
|
|
struct TempArena
|
|
{
|
|
Arena* arena;
|
|
Node!(ArenaPool)* start_node;
|
|
u64 start_pos;
|
|
}
|
|
|
|
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[]
|
|
Alloc(T)(u64 count)
|
|
{
|
|
void* mem = pureMalloc(T.sizeof * count);
|
|
memset(mem, 0, T.sizeof * count);
|
|
return (cast(T*)mem)[0 .. count];
|
|
}
|
|
|
|
T[]
|
|
AllocCopy(T)(T[] target)
|
|
{
|
|
T[] arr = Alloc!(T)(target.length);
|
|
arr[] = target[];
|
|
return arr;
|
|
}
|
|
|
|
T[]
|
|
AllocCopySlice(T)(T[] target, u64 start, u64 len)
|
|
{
|
|
T[] arr = Alloc!(T)(len);
|
|
arr[0 .. $] = target[start .. start+len];
|
|
return arr;
|
|
}
|
|
|
|
T[]
|
|
AllocArray(T)(u64 count)
|
|
{
|
|
return Alloc!(T)(count);
|
|
}
|
|
|
|
T[]
|
|
ReallocArray(T)(T[] arr, u64 count)
|
|
{
|
|
void* mem = pureRealloc(arr.ptr, T.sizeof * count);
|
|
return (cast(T*)mem)[0 .. count];
|
|
}
|
|
|
|
Arena
|
|
CreateArena(u64 size)
|
|
{
|
|
Arena arena = {
|
|
def_size: size,
|
|
};
|
|
|
|
AddArenaPool(&arena, size);
|
|
|
|
return arena;
|
|
}
|
|
|
|
TempArena
|
|
BeginTempArena(Arena* arena)
|
|
{
|
|
TempArena t = {
|
|
arena: arena,
|
|
};
|
|
|
|
auto n = arena.pools.first;
|
|
for(;;)
|
|
{
|
|
if(n.next == null)
|
|
{
|
|
t.start_node = n;
|
|
t.start_pos = n.value.pos;
|
|
break;
|
|
}
|
|
|
|
n = n.next;
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
void
|
|
End(TempArena* t)
|
|
{
|
|
bool resetting = false;
|
|
for(auto n = t.arena.pools.first; n != null; n = n.next)
|
|
{
|
|
if(t.start_node == n)
|
|
{
|
|
n.value.pos = t.start_pos;
|
|
resetting = true;
|
|
}
|
|
else if(resetting)
|
|
{
|
|
n.value.pos = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
T[]
|
|
AllocCopy(T)(TempArena* t, T[] target)
|
|
{
|
|
return AllocCopy!(T)(t.arena, target);
|
|
}
|
|
|
|
T[]
|
|
Alloc(T)(TempArena* t, u64 count)
|
|
{
|
|
return Alloc!(T)(t.arena, count);
|
|
}
|
|
|
|
T[]
|
|
AllocArray(T)(TempArena* t, u64 count)
|
|
{
|
|
return Alloc!(T)(t.arena, count);
|
|
}
|
|
|
|
T*
|
|
Alloc(T)(TempArena* t)
|
|
{
|
|
return Alloc!(T)(t.arena);
|
|
}
|
|
|
|
void
|
|
AddArenaPool(Arena* arena, u64 size)
|
|
{
|
|
u8* mem = Alloc!(u8)(size + Node!(ArenaPool).sizeof).ptr;
|
|
|
|
Node!(ArenaPool)* node = cast(Node!(ArenaPool)*)mem;
|
|
|
|
node.value.mem = (cast(u8*)mem) + Node!(ArenaPool).sizeof;
|
|
node.value.pos = 0;
|
|
node.value.length = size;
|
|
|
|
assert(node.value.mem != null, "Unable to allocate memory for arena");
|
|
|
|
SLLPushFront(&arena.pools, node, null);
|
|
}
|
|
|
|
T[]
|
|
Alloc(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[]
|
|
AllocArray(T)(Arena* arena, u64 count)
|
|
{
|
|
return Alloc!(T)(arena, count);
|
|
}
|
|
|
|
T[]
|
|
AllocCopy(T)(Arena* arena, T[] target)
|
|
{
|
|
T[] arr = Alloc!(T)(arena, target.length);
|
|
arr[] = target[];
|
|
return arr;
|
|
}
|
|
|
|
T[]
|
|
AllocCopySlice(T)(Arena* arena, T[] target, u64 start, u64 len)
|
|
{
|
|
T[] arr = Alloc!(T)(arena, len);
|
|
arr[0 .. $] = target[start .. start+len];
|
|
return arr;
|
|
}
|
|
|
|
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)
|
|
{
|
|
void* ptr = null;
|
|
|
|
uintptr mem_pos, current, offset;
|
|
Node!(ArenaPool)* node = arena.pools.first;
|
|
while (true)
|
|
{
|
|
if(node == null)
|
|
{
|
|
if(size > arena.def_size)
|
|
{
|
|
size += arena.def_size;
|
|
}
|
|
|
|
AddArenaPool(arena, Max(size, arena.def_size));
|
|
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 <= node.value.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)
|
|
{
|
|
Free(node);
|
|
node = node.next;
|
|
}
|
|
}
|
|
|
|
void
|
|
FreeArray(T)(T[] arr)
|
|
{
|
|
pureFree(arr.ptr);
|
|
}
|
|
|
|
void
|
|
Free(T)(T* ptr)
|
|
{
|
|
pureFree(ptr);
|
|
}
|
|
|
|
void
|
|
ResetScratch(u64 size)
|
|
{
|
|
if(!g_scratch.init)
|
|
{
|
|
g_scratch.arena = CreateArena(size);
|
|
g_scratch.init = true;
|
|
}
|
|
|
|
Reset(&g_scratch.arena);
|
|
}
|
|
|
|
T*
|
|
ScratchAlloc(T)()
|
|
{
|
|
return Alloc!(T)(&g_scratch.arena);
|
|
}
|
|
|
|
T[]
|
|
ScratchAlloc(T)(u64 count)
|
|
{
|
|
return AllocArray!(T)(&g_scratch.arena, count);
|
|
}
|
|
|
|
T[]
|
|
ScratchAllocCopy(T)(T[] target)
|
|
{
|
|
T[] arr = ScratchAlloc!(T)(target.length);
|
|
arr[] = target[];
|
|
return arr;
|
|
}
|
|
|
|
T[]
|
|
ScratchAllocCopySlice(T)(T[] target, u64 start, u64 len)
|
|
{
|
|
T[] arr = ScratchAlloc!(T)(len);
|
|
arr[0 .. $] = target[start .. start+len];
|
|
return arr;
|
|
}
|
|
|
|
unittest
|
|
{
|
|
{
|
|
u64[5] arr = [1, 2, 3, 4, 5];
|
|
|
|
u64[] copy = AllocCopy!(u64)(arr);
|
|
|
|
assert(arr == copy);
|
|
}
|
|
|
|
{
|
|
Arena a = CreateArena(64);
|
|
|
|
u64[] arr = Alloc!(u64)(&a, 128);
|
|
}
|
|
}
|