diff --git a/arena_allocator.c b/arena_allocator.c index ced0ee5..1fce0bf 100644 --- a/arena_allocator.c +++ b/arena_allocator.c @@ -1,4 +1,6 @@ #include "cig.h" +#include +#include void *arena_allocator_alloc_func( @@ -7,20 +9,105 @@ void *arena_allocator_alloc_func( const char *file, int line ) { - allocator_t std_alloc = allocator_stdlib(); buffer_allocator_t ba = (buffer_allocator_t) { .size=dyn_array_length(this->bytes), .capacity=dyn_array_capacity(this->bytes), .data=this->bytes }; + void *allocated = buffer_allocator_alloc(&ba, bytes); + if (allocated != NULL) { + return allocated; + } + allocated = borrow_allocator_alloc_func(&this->borrow_allocator, bytes, file, line); + if (allocated != NULL) { + this->total_allocated += bytes; + return allocated; + } + return NULL; } -void arena_allocator_reset(arena_allocator_t *this) { +void arena_allocator_reset(arena_allocator_t *this, const char *file, int line) { + borrow_allocator_free_all(&this->borrow_allocator); + if (this->bytes == NULL) { + this->bytes = dyn_array_create_non_crashing_func( + (dyn_array_create_non_crashing_func_args_t) { + .allocator=allocator_stdlib(), + .itemsize=sizeof(uint8_t), + .initial_capacity=this->total_allocated, + .file=file, + .line=line, + } + ); + } + if (this->bytes == NULL) { + return; + } + if (dyn_array_capacity(this->bytes) < this->total_allocated) { + size_t needed_bytes = this->total_allocated - dyn_array_length(this->bytes); + uint8_t *new_bytes = dyn_array_grow_non_crashing_func( + this->bytes, + needed_bytes, + file, + line + ); + if (new_bytes == NULL) { + dyn_array_shrink_func( + this->bytes, + dyn_array_length(this->bytes), + file, + line + ); + return; + } else { + this->bytes = new_bytes; + } + } + if (this->bytes == NULL) { + return; + } + dyn_array_shrink_func(this->bytes, dyn_array_length(this->bytes), file, line); + return; } void arena_allocator_destroy(arena_allocator_t *this) { + borrow_allocator_free_all(&this->borrow_allocator); + dyn_array_destroy(this->bytes); } +static void *arena_allocator_alloc_impl(void *this, size_t bytes, const char *file, int line) { + return arena_allocator_alloc_func( + (arena_allocator_t*) this, + bytes, + file, + line + ); +} +static void *arena_allocator_resize_impl(void *this, void *old_ptr, size_t bytes, const char *file, int line) { + (void)this; + (void)file; + (void)line; + assert( false && "TODO: This is fucky. I need to see whether the allocation is in the buffer, if not then it is one of the borrow allocator nodes. I need an actual implementation here."); + return realloc(old_ptr, bytes); + return arena_allocator_alloc_func( + (arena_allocator_t*) this, + bytes, + file, + line + ); +} +static void arena_allocator_free_impl(void *this, void *ptr, const char *file, int line) { + (void)this; + (void)file; + (void)line; + free(ptr); +} + +static const allocator_vtbl_t stdlib_vtbl = { + .alloc = arena_allocator_alloc_impl, + .resize = arena_allocator_resize_impl, + .free = arena_allocator_free_impl, +}; + allocator_t arena_allocator_interface(arena_allocator_t *this) { } diff --git a/borrow_allocator.c b/borrow_allocator.c index 4bad7fd..0e8c0e8 100644 --- a/borrow_allocator.c +++ b/borrow_allocator.c @@ -46,7 +46,7 @@ void borrow_allocator_free(borrow_allocator_t *this, void *old_ptr) { free(node); } -void borrow_allocator_reset(borrow_allocator_t *this) { +void borrow_allocator_free_all(borrow_allocator_t *this) { if (this->head == NULL) { return; } diff --git a/cig.h b/cig.h index a28f302..820c43d 100644 --- a/cig.h +++ b/cig.h @@ -78,7 +78,7 @@ void *borrow_allocator_resize_func(borrow_allocator_t *this, void *old_ptr, size #define borrow_allocator_resize(this, old_ptr, bytes) borrow_allocator_resize_func(this, old_ptr, bytes, __FILE__, __LINE__) void borrow_allocator_free(borrow_allocator_t *this, void *old_ptr); // Free all allocations done by this allocator. -void borrow_allocator_reset(borrow_allocator_t *this); +void borrow_allocator_free_all(borrow_allocator_t *this); size_t borrow_allocator_count_allocations(borrow_allocator_t *this); // Check that all allocations have been freed, or print a list of files and // lines where made that haven't been freed to stderr and then exit the program @@ -101,7 +101,7 @@ allocator_t borrow_allocator_interface(borrow_allocator_t *this); borrow_allocator_interface(&borrow_allocator_create()); \ !((borrow_allocator_t *)NAME.this)->head; \ ((borrow_allocator_t *)NAME.this)->head = \ - (borrow_allocator_reset(((borrow_allocator_t *)NAME.this)), \ + (borrow_allocator_free_all(((borrow_allocator_t *)NAME.this)), \ (linked_allocation_node_t *)1)) \ for (int UNIQUE = 0; UNIQUE < 1; UNIQUE++) @@ -145,7 +145,7 @@ void *arena_allocator_alloc_func( #define arena_allocator_alloc(THIS, BYTES) \ arena_allocator_alloc_func(THIS, BYTES, __FILE__, __LINE__) -void arena_allocator_reset(arena_allocator_t *this); +void arena_allocator_reset(arena_allocator_t *this, const char *file, int line); void arena_allocator_destroy(arena_allocator_t *this); allocator_t arena_allocator_interface(arena_allocator_t *this); diff --git a/test_borrow_allocator.c b/test_borrow_allocator.c index 9d8d4d4..7b89344 100644 --- a/test_borrow_allocator.c +++ b/test_borrow_allocator.c @@ -8,7 +8,7 @@ Test(borrow_allocator, test) { *ptr = EXPECT; cr_assert_eq(*ptr, EXPECT); cr_assert_eq(1, borrow_allocator_count_allocations(&balloc)); - borrow_allocator_reset(&balloc); + borrow_allocator_free_all(&balloc); cr_assert_eq(0, borrow_allocator_count_allocations(&balloc)); borrow_allocator_assert_all_freed(&balloc); }