#include "arena_allocator.h" #include #include #include #define DEFAUL_REGION_SIZE 1048576 /* 8 * 1024 * 1024 = 8MB */ Region *new_region(size_t capacity) { if (capacity < DEFAUL_REGION_SIZE) { capacity = DEFAUL_REGION_SIZE; } Region *region = malloc(capacity + sizeof(Region)); assert(region != NULL); *region = (Region){.next = NULL, .capacity = capacity, .cursor = 0}; return region; } Arena arena_init(Arena *parent, size_t capacity) { Region *region = new_region(capacity); if (parent != NULL) { // Allocate new arena in parent to reduce likelyhood of loss Arena *current_arena = arena_alloc(parent, sizeof(Arena)); *current_arena = (Arena){.begin = region, .end = region, .child = NULL, .sibling = NULL}; // if parent has no children this arena is now it's child if (parent->child == NULL) { parent->child = current_arena; return *current_arena; } // Push the arena onto the first childs sibling list current_arena->sibling = parent->child; parent->child = current_arena; return *current_arena; } // This is the root of the arena tree Arena arena = { .begin = region, .end = region, .child = NULL, .sibling = NULL}; return arena; } void arena_deinit(Arena *arena) { if (arena == NULL) { return; } // Recursively deinit children while (arena->child != NULL) { Arena *current_child = arena->child; arena->child = current_child->sibling; arena_deinit(current_child); } // actually free the data assert(arena->begin != NULL && arena->end != NULL); Region *region = arena->begin; while (region != NULL) { Region *next_region = region->next; free(region); region = next_region; } *arena = (Arena){.begin = NULL, .end = NULL}; } void *arena_alloc(Arena *arena, size_t size) { // TODO: only align when needed size = (size + 7) & ~7; // align size increase to multiple of 8 Region *region = arena->end; assert(region != NULL); if (region->cursor + size > region->capacity) { region->next = new_region(size); arena->end = region->next; region = region->next; } void *result = ®ion->data[region->cursor]; region->cursor += size; return result; } // void *arena_clear(Arena *arena) { // arena->size = 0; // return arena->data; // }