diff --git a/src/arena_allocator.c b/src/arena_allocator.c index 4bdf4bc..7fae31d 100644 --- a/src/arena_allocator.c +++ b/src/arena_allocator.c @@ -65,6 +65,13 @@ void arena_deinit(Arena *arena) { arena_deinit(current_child); } + // Run deinit tasks before freeing data + while (arena->deinit_task_top != NULL) { + assert(arena->deinit_task_top->func_ptr != NULL); + arena->deinit_task_top->func_ptr(arena->deinit_task_top->func_param); + arena->deinit_task_top = arena->deinit_task_top->next; + } + // actually free the data assert(arena->begin != NULL && arena->end != NULL); Region *region = arena->begin; @@ -117,7 +124,11 @@ void *arena_alloc(Arena *arena, size_t size) { return result; } -// void *arena_clear(Arena *arena) { -// arena->size = 0; -// return arena->data; -// } +void arena_run_on_deinit_push(Arena *arena, ArenaDeinitTask task) { + ArenaDeinitTask *job = arena_alloc(arena, sizeof(ArenaDeinitTask)); + *job = task; + + ArenaDeinitTask *next_job = arena->deinit_task_top; + arena->deinit_task_top = job; + job->next = next_job; +} diff --git a/src/arena_allocator.h b/src/arena_allocator.h index 0c48a10..bffc803 100644 --- a/src/arena_allocator.h +++ b/src/arena_allocator.h @@ -10,6 +10,14 @@ struct Region_s { unsigned char data[]; }; +typedef struct ArenaDeinitTask_s ArenaDeinitTask; +struct ArenaDeinitTask_s { + void *func_param; + void (*func_ptr)(void *); + ArenaDeinitTask *next; +}; +ArenaDeinitTask ArenaDeinitTask_default = {NULL}; + typedef struct Arena_s Arena; struct Arena_s { Arena *parent; @@ -17,10 +25,13 @@ struct Arena_s { Arena *sibling; Region *begin; Region *end; + ArenaDeinitTask *deinit_task_top; }; Arena *arena_init(Arena *parent, size_t capacity); void arena_deinit(Arena *arena); +void arena_run_on_deinit_push(Arena *arena, ArenaDeinitTask task); + void *arena_alloc(Arena *arena, size_t size); // void *arena_clear(Arena *arena);