WIP
This commit is contained in:
+41
-1
@@ -1,8 +1,48 @@
|
|||||||
#include "cig.h"
|
#include "cig.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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) {
|
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) {
|
allocator_t allocator_from_arena(arena_allocator_t *this) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
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 MAX_ALIGN ((size_t) sizeof(any_align_t))
|
||||||
#define KB (1024)
|
#define KB (1024)
|
||||||
#define MB (KB * KB)
|
#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 OFFSET(STRUCT, FIELD) ((size_t) (&((STRUCT*) NULL)->FIELD))
|
||||||
#define PTR_FROM_FIELD_PTR(STRUCT, FIELD, PTR) ((STRUCT *) (((char *) PTR) - OFFSET(STRUCT, 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
|
// Contains all operations an allocator can do. Similar interface to sdtlibs
|
||||||
// malloc, realloc and free.
|
// malloc, realloc and free.
|
||||||
typedef struct allocator_vtbl {
|
typedef struct allocator_vtbl {
|
||||||
@@ -89,15 +88,7 @@ typedef struct arena_allocator {
|
|||||||
allocator_t allocator;
|
allocator_t allocator;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
// this may grow outside the allocated data. When data is not large enough,
|
size_t bytes_outside_data;
|
||||||
// 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;
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
} arena_allocator_t;
|
} arena_allocator_t;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user