diff --git a/arena_allocator.c b/arena_allocator.c index 0d5ee6a..b0d2988 100644 --- a/arena_allocator.c +++ b/arena_allocator.c @@ -1,8 +1,48 @@ #include "cig.h" +#include + +static void arena_reset(arena_allocator_t *this) { + if (0 < this->bytes_outside_data) { + this->capacity += this->bytes_outside_data; + this->bytes_outside_data = 0; + allocator_reset(this->allocator); + this->data = NULL; + } + if (this->data == NULL) { + this->data = allocator_alloc(this->allocator, this->capacity); + } + this->size = 0; +} static void *arena_alloc(arena_allocator_t *this, size_t bytes) { - + // Assume that the this->size index already points to an address that is + // divisible by MAX_ALIGN. The following is a magic formula from the GPT + // gods that rounds up bytes to a multiple of MAX_ALIGN. + // TODO: write tests that assert that this formula is always correct. + bytes = (bytes + MAX_ALIGN - 1) / MAX_ALIGN * MAX_ALIGN; + size_t remaining = this->capacity - this->size; + if (remaining < bytes) { + this->bytes_outside_data += bytes; + return allocator_alloc(this->allocator, bytes); + } + void *ptr = &this->data[this->size]; + this->size += bytes; + return ptr; } +static void *arena_resize(arena_allocator_t *this, void *old_ptr, size_t bytes) { + bool is_old_ptr_in_data = this->data <= old_ptr && old_ptr < &this->data[this->size] + // TODO: implement this +} + +// typedef struct arena_allocator { +// allocator_t allocator; +// size_t size; +// size_t capacity; +// size_t bytes_outside_data; +// uint8_t *data; +// } arena_allocator_t; + + allocator_t allocator_from_arena(arena_allocator_t *this) { } diff --git a/cig.h b/cig.h index 2864878..febc9f0 100644 --- a/cig.h +++ b/cig.h @@ -6,7 +6,7 @@ #include #include -typedef union any_align { char c; int i; long l; long long ll; float f; double d; void *p; } any_align_t; +typedef union any_align { char c; int i; long l; long long ll; float f; double d; void *p; long double ld; } any_align_t; #define MAX_ALIGN ((size_t) sizeof(any_align_t)) #define KB (1024) #define MB (KB * KB) @@ -14,7 +14,6 @@ typedef union any_align { char c; int i; long l; long long ll; float f; double d #define OFFSET(STRUCT, FIELD) ((size_t) (&((STRUCT*) NULL)->FIELD)) #define PTR_FROM_FIELD_PTR(STRUCT, FIELD, PTR) ((STRUCT *) (((char *) PTR) - OFFSET(STRUCT, FIELD))) - // Contains all operations an allocator can do. Similar interface to sdtlibs // malloc, realloc and free. typedef struct allocator_vtbl { @@ -89,15 +88,7 @@ typedef struct arena_allocator { allocator_t allocator; size_t size; size_t capacity; - // this may grow outside the allocated data. When data is not large enough, - // the backing allocator will be used to allocate exactly what the user - // asked for, and the total_allocated will grow for each such allocation. - // On the next reset if total_allocated is larger than capacity, we know - // that there are allocations outside the large buffer, so we reset the - // allocator, and allocate a new buffer that is the size of - // total_allocated, and set the new size of the capacity. Otherwise the - // size is just reset to 0. plus something else I think I forgot. - size_t total_allocated_bytes; + size_t bytes_outside_data; uint8_t *data; } arena_allocator_t;