implementation of arena constructed on reserve/commit/decommit/release

This commit is contained in:
Allen Webster
2021-07-20 21:23:14 -07:00
parent 81292bfb24
commit d937a99b51
2 changed files with 193 additions and 29 deletions
+179 -13
View File
@@ -1,8 +1,17 @@
// LICENSE AT END OF FILE (MIT).
// NOTE(allen): Notes on overrides/macro options:
// #define MD_IMPL_FileIterIncrement -> override default implementation
// #define MD_NO_DEFAULT_IMPL -> skip OS specific code for implementation
// Individual Overridables:
// #define MD_IMPL_FileIterIncrement
// #define MD_IMPL_Alloc
// #define MD_IMPL_Reserve
// #define MD_IMPL_Commit
// #define MD_IMPL_Decommit
// #define MD_IMPL_Release
// #define MD_IMPL_ArenaNew
// #define MD_IMPL_ArenaRelease
// Default Implementation Controls
// #define MD_NO_DEFAULT_IMPL -> skip code for all default implementations
#if !defined(MD_NO_DEFAULT_IMPL)
# define MD_NO_DEFAULT_IMPL 0
@@ -79,6 +88,40 @@ MD_WIN32_FileIterIncrement(MD_FileIter *it, MD_String8 path, MD_FileInfo *out_in
return result;
}
#if !defined(MD_IMPL_Reserve)
# define MD_IMPL_Reserve MD_WIN32_Reserve
#endif
#if !defined(MD_IMPL_Commit)
# define MD_IMPL_Commit MD_WIN32_Commit
#endif
#if !defined(MD_IMPL_Decommit)
# define MD_IMPL_Decommit MD_WIN32_Decommit
#endif
#if !defined(MD_IMPL_Release)
# define MD_IMPL_Release MD_WIN32_Release
#endif
static void*
MD_WIN32_Reserve(MD_u64 size){
void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
return(result);
}
static void
MD_WIN32_Commit(void *ptr, MD_u64 size){
VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE);
}
static void
MD_WIN32_Decommit(void *ptr, MD_u64 size){
VirtualFree(ptr, size, MEM_DECOMMIT);
}
static void
MD_WIN32_Release(void *ptr, MD_u64 size){
VirtualFree(ptr, 0, MEM_RELEASE);
}
#endif
//~/////////////////////////////////////////////////////////////////////////////
@@ -163,14 +206,123 @@ MD_LINUX_FileIterIncrement(MD_FileIter *opaque_it, MD_String8 path, MD_FileInfo
#endif
//~/////////////////////////////////////////////////////////////////////////////
///////////// MD Arena From Reserve/Commit/Decommit/Release ////////////////////
////////////////////////////////////////////////////////////////////////////////
#define MD_ArenaDefault_HeaderSize 64
#define MD_ArenaDefault_CommitSize (1 << 20)
typedef struct MD_ArenaDefault MD_ArenaDefault;
struct MD_ArenaDefault{
MD_ArenaFunc *func;
MD_u64 pos;
MD_u64 cmt;
MD_u64 cap;
MD_u64 align;
};
MD_StaticAssert(sizeof(MD_ArenaDefault) <= MD_ArenaDefault_HeaderSize, arena_def_size_check);
#define MD_IMPL_ArenaNew MD_ArenaDefaultNew
#define MD_IMPL_ArenaRelease MD_ArenaDefaultRelease
static MD_IntPtr
MD_ArenaDefaultImpl(MD_Arena *arena_opq, MD_ArenaOperation op, MD_u64 v){
MD_ArenaDefault *arena = (MD_ArenaDefault*)arena_opq;
MD_u8 *buf = (MD_u8*)arena_opq;
MD_IntPtr result = MD_ZERO_STRUCT;
switch (op){
case MD_ArenaOperation_GetPos:
{
result.u64 = arena->pos;
}break;
case MD_ArenaOperation_GetCap:
{
result.u64 = arena->cap;
}break;
case MD_ArenaOperation_Push:
{
if (arena->pos + v <= arena->cap){
MD_u64 pos = arena->pos;
MD_u64 pos_clamped = ((pos > MD_ArenaDefault_HeaderSize) ? pos : MD_ArenaDefault_HeaderSize);
MD_u64 new_pos = pos_clamped + v;
MD_u64 align_m1 = arena->align - 1;
MD_u64 new_pos_aligned = (new_pos + align_m1)&(~align_m1);
MD_u64 new_pos_clamped = ((arena->cap < new_pos_aligned) ? arena->cap : new_pos_aligned);
result.ptr = buf + pos;
arena->pos = new_pos_aligned;
if (new_pos_clamped > arena->cmt){
MD_u64 cmt_amt_raw = new_pos_clamped - arena->cmt;
MD_u64 cmt_align_m1 = MD_ArenaDefault_CommitSize - 1;
MD_u64 cmt_amt = (cmt_amt_raw + cmt_align_m1)&(~cmt_align_m1);
MD_IMPL_Commit(buf + arena->cmt, cmt_amt);
arena->cmt += cmt_amt;
}
}
}break;
case MD_ArenaOperation_PopTo:
{
MD_u64 pos_clamped = ((v > MD_ArenaDefault_HeaderSize) ? v : MD_ArenaDefault_HeaderSize);
arena->pos = pos_clamped;
}break;
case MD_ArenaOperation_PushAlign:
{
MD_u64 pos = arena->pos;
MD_u64 pos_clamped = ((pos > MD_ArenaDefault_HeaderSize) ? pos : MD_ArenaDefault_HeaderSize);
MD_u64 align_m1 = arena->align - 1;
MD_u64 new_pos_aligned = (pos_clamped + align_m1)&(~align_m1);
MD_u64 new_pos_clamped = ((arena->cap < new_pos_aligned) ? arena->cap : new_pos_aligned);
arena->pos = new_pos_clamped;
}break;
case MD_ArenaOperation_SetAutoAlign:
{
arena->align = v;
}break;
}
return(result);
}
static MD_Arena*
MD_ArenaDefaultNew(MD_u64 cap){
void *mem = MD_IMPL_Reserve(cap);
MD_u64 cmt = ((MD_ArenaDefault_CommitSize < cap) ? MD_ArenaDefault_CommitSize : cap);
MD_IMPL_Commit(mem, cmt);
MD_ArenaDefault *arena = (MD_ArenaDefault*)mem;
arena->func = MD_ArenaDefaultImpl;
arena->pos = MD_ArenaDefault_HeaderSize;
arena->cmt = cmt;
arena->cap = cap;
arena->align = sizeof(void*);
return((MD_Arena*)arena);
}
static void
MD_ArenaDefaultRelease(MD_Arena *arena_opq){
MD_ArenaDefault *arena = (MD_ArenaDefault*)arena_opq;
MD_u64 cap = arena->cap;
MD_IMPL_Release(arena, cap);
}
//~/////////////////////////////////////////////////////////////////////////////
//////////////////////// MD Library Implementation /////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#if !defined(MD_IMPL_FileIterIncrement)
# error Missing implementation for MD_IMPL_FileIterIncrement
#if !defined(MD_IMPL_Alloc)
# error Missing implementation for MD_IMPL_Alloc
#endif
#if !defined(MD_IMPL_ArenaNew)
# error Missing implementation for MD_IMPL_ArenaNew
#endif
#if !defined(MD_IMPL_ArenaRelease)
# error Missing implementation for MD_IMPL_ArenaRelease
#endif
#define MD_FUNCTION_IMPL MD_FUNCTION
#define MD_PRIVATE_FUNCTION_IMPL MD_FUNCTION_IMPL
@@ -205,16 +357,18 @@ static MD_Node _md_nil_node =
//~ Memory Operations
MD_FUNCTION_IMPL void
MD_FUNCTION_IMPL void*
MD_MemoryZero(void *memory, MD_u64 size)
{
memset(memory, 0, size);
return(memory);
}
MD_FUNCTION_IMPL void
MD_FUNCTION_IMPL void*
MD_MemoryCopy(void *dest, void *src, MD_u64 size)
{
memcpy(dest, src, size);
return(dest);
}
MD_FUNCTION_IMPL void *
@@ -232,15 +386,13 @@ MD_AllocZero(MD_u64 size)
//~ Arena Functions
MD_FUNCTION void*
MD_ArenaPush(MD_Arena *arena, MD_u64 v)
{
MD_ArenaPush(MD_Arena *arena, MD_u64 v){
MD_IntPtr result = arena->func(arena, MD_ArenaOperation_Push, v);
return(result.ptr);
}
MD_FUNCTION MD_ArenaTemp
MD_ArenaBeginTemp(MD_Arena *arena)
{
MD_ArenaBeginTemp(MD_Arena *arena){
MD_IntPtr pos = arena->func(arena, MD_ArenaOperation_GetPos, 0);
MD_ArenaTemp result = MD_ZERO_STRUCT;
result.arena = arena;
@@ -249,8 +401,7 @@ MD_ArenaBeginTemp(MD_Arena *arena)
}
MD_FUNCTION void
MD_ArenaEndTemp(MD_ArenaTemp temp)
{
MD_ArenaEndTemp(MD_ArenaTemp temp){
temp.arena->func(temp.arena, MD_ArenaOperation_PopTo, temp.pos);
}
@@ -264,6 +415,21 @@ MD_ArenaPushAlign(MD_Arena *arena, MD_u64 v){
arena->func(arena, MD_ArenaOperation_PushAlign, v);
}
MD_FUNCTION void
MD_ArenaClear(MD_Arena *arena){
arena->func(arena, MD_ArenaOperation_PopTo, 0);
}
MD_FUNCTION MD_Arena*
MD_ArenaNew(MD_u64 cap){
return(MD_IMPL_ArenaNew(cap));
}
MD_FUNCTION void
MD_ArenaRelease(MD_Arena *arena){
MD_IMPL_ArenaRelease(arena);
}
//~ Characters
+14 -16
View File
@@ -1,11 +1,6 @@
//~ Metadesk Library
// LICENSE AT END OF FILE (MIT).
// NOTE(allen): "Plugin" functionality
//
// MD_b32 MD_IMPL_FileIterIncrement(MD_FileIter*, MD_String8, MD_FileInfo*) - optional
// void* MD_IMPL_Alloc(MD_u64) - required
//
//~ Metadesk Library
#ifndef MD_H
#define MD_H
@@ -260,15 +255,14 @@ typedef double MD_f64;
//~ Abstract Arena
typedef union MD_IntPtr MD_IntPtr;
union MD_IntPtr
{
union MD_IntPtr{
MD_u64 u64;
void *ptr;
};
typedef enum MD_ArenaOperation
{
typedef enum MD_ArenaOperation{
MD_ArenaOperation_GetPos,
MD_ArenaOperation_GetCap,
MD_ArenaOperation_Push,
MD_ArenaOperation_PopTo,
MD_ArenaOperation_PushAlign,
@@ -278,16 +272,14 @@ typedef enum MD_ArenaOperation
typedef MD_IntPtr MD_ArenaFunc(struct MD_Arena *arena, MD_ArenaOperation op, MD_u64 v);
typedef struct MD_Arena MD_Arena;
struct MD_Arena
{
struct MD_Arena{
MD_ArenaFunc *func;
};
//~ Arena Helpers
typedef struct MD_ArenaTemp MD_ArenaTemp;
struct MD_ArenaTemp
{
struct MD_ArenaTemp{
MD_Arena *arena;
MD_u64 pos;
};
@@ -692,8 +684,8 @@ struct MD_FileIter
//~ Memory Operations
MD_FUNCTION void MD_MemoryZero(void *memory, MD_u64 size);
MD_FUNCTION void MD_MemoryCopy(void *dst, void *src, MD_u64 size);
MD_FUNCTION void* MD_MemoryZero(void *memory, MD_u64 size);
MD_FUNCTION void* MD_MemoryCopy(void *dst, void *src, MD_u64 size);
MD_FUNCTION void* MD_AllocZero(MD_u64 size);
#define MD_PushArray(T,c) (T*)MD_AllocZero(sizeof(T)*(c))
@@ -710,8 +702,14 @@ MD_FUNCTION MD_ArenaTemp MD_ArenaBeginTemp(MD_Arena *arena);
MD_FUNCTION void MD_ArenaEndTemp(MD_ArenaTemp temp);
MD_FUNCTION void MD_ArenaSetAlign(MD_Arena *arena, MD_u64 v);
MD_FUNCTION void MD_ArenaPushAlign(MD_Arena *arena, MD_u64 v);
MD_FUNCTION void MD_ArenaClear(MD_Arena *arena);
#define MD_PushArrayAr(a,T,c) (T*)(MD_ArenaPush((a), sizeof(T)*(c)))
#define MD_PushArrayZeroAr(a,T,c) (T*)(MD_MemoryZero(MD_ArenaPush((a), sizeof(T)*(c)),\
sizeof(T)*(c)))
MD_FUNCTION MD_Arena* MD_ArenaNew(MD_u64 cap);
MD_FUNCTION void MD_ArenaRelease(MD_Arena *arena);
//~ Characters