refactor(all): Fixed alloc and moved growing logic to another function
OK, so evrything was a fucknig mess, it still kinda is, AI helped me to clean my own mess, it really sucks but the fucking debugger and address sanitizer were not working, also, there were small small errors so no big deal but still, a bit sad, also changed a the way i cast from uint8_t to double and int in the tests, may change that i guess, verything else i might say is good :)
This commit is contained in:
120
src/arena.c
120
src/arena.c
@@ -6,6 +6,13 @@
|
||||
#include <string.h>
|
||||
|
||||
ArenaResult arena_init(size_t capacity) {
|
||||
if (capacity < 1) {
|
||||
ArenaResult err = {
|
||||
.is_valid = false,
|
||||
.err = ARENA_INVALID_SIZE,
|
||||
};
|
||||
return err;
|
||||
}
|
||||
|
||||
void *buffer = malloc(capacity);
|
||||
if (buffer == NULL) {
|
||||
@@ -16,14 +23,6 @@ ArenaResult arena_init(size_t capacity) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (capacity < 1) {
|
||||
ArenaResult err = {
|
||||
.is_valid = false,
|
||||
.err = ARENA_INVALID_SIZE,
|
||||
};
|
||||
return err;
|
||||
}
|
||||
|
||||
Arena new_arena = {
|
||||
.buffer = buffer,
|
||||
.capacity = capacity,
|
||||
@@ -38,13 +37,10 @@ ArenaResult arena_init(size_t capacity) {
|
||||
}
|
||||
|
||||
void arena_destroy(Arena *arena) {
|
||||
if (arena == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(arena->buffer);
|
||||
arena->buffer = NULL;
|
||||
arena->offset = 0;
|
||||
arena->capacity = 0;
|
||||
free(arena->buffer);
|
||||
}
|
||||
|
||||
ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) {
|
||||
@@ -56,16 +52,17 @@ ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) {
|
||||
return err;
|
||||
}
|
||||
|
||||
SizeResult new_offset = align_arena_offset(arena, alignment);
|
||||
if (!new_offset.is_valid) {
|
||||
SizeResult padding = get_arena_align_padding(arena, alignment);
|
||||
if (!padding.is_valid) {
|
||||
ArenaPointer err = {
|
||||
.is_valid = false,
|
||||
.err = new_offset.err,
|
||||
.err = padding.err,
|
||||
};
|
||||
return err;
|
||||
}
|
||||
|
||||
if (new_offset.val + size >= arena->capacity) {
|
||||
|
||||
if (arena->offset + padding.val >= arena->capacity) {
|
||||
ArenaPointer err = {
|
||||
.is_valid = false,
|
||||
.err = ARENA_OUT_OF_SPACE,
|
||||
@@ -73,15 +70,57 @@ ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) {
|
||||
return err;
|
||||
}
|
||||
|
||||
arena->offset = new_offset.val;
|
||||
if (arena->offset > SIZE_MAX - padding.val - size) {
|
||||
ArenaPointer err = {
|
||||
.is_valid = false,
|
||||
.err = ARENA_CAPACITY_OVERFLOW,
|
||||
};
|
||||
return err;
|
||||
}
|
||||
|
||||
size_t aligned_offset = arena->offset + padding.val;
|
||||
|
||||
arena->offset = aligned_offset + size;
|
||||
ArenaPointer val = {
|
||||
.is_valid = true,
|
||||
.address = arena->buffer + arena->offset,
|
||||
.address = arena->buffer + aligned_offset,
|
||||
};
|
||||
return val;
|
||||
}
|
||||
|
||||
ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment) {
|
||||
if (arena == NULL) {
|
||||
return ARENA_NULL_ARG;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
SizeResult padding = get_arena_align_padding(arena, alignment);
|
||||
if (!padding.is_valid) {
|
||||
return padding.err;
|
||||
}
|
||||
|
||||
if (arena->offset > SIZE_MAX - padding.val - size) {
|
||||
return ARENA_CAPACITY_OVERFLOW;
|
||||
}
|
||||
|
||||
size_t required = arena->offset + padding.val + size;
|
||||
|
||||
if (required <= arena->capacity) {
|
||||
return ARENA_OK;
|
||||
}
|
||||
|
||||
size_t new_capacity;
|
||||
if (mul_size_t_safe(arena->capacity, 2, &new_capacity)) {
|
||||
return ARENA_CAPACITY_OVERFLOW;
|
||||
}
|
||||
|
||||
ArenaErr err = arena_realloc(arena, new_capacity);
|
||||
if (err != ARENA_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArenaPointer arena_push(Arena *arena, void *data, size_t size, size_t alignment) {
|
||||
if (arena == NULL || data == NULL) {
|
||||
ArenaPointer bad_pointer = {
|
||||
@@ -91,35 +130,20 @@ ArenaPointer arena_push(Arena *arena, void *data, size_t size, size_t alignment)
|
||||
return bad_pointer;
|
||||
}
|
||||
|
||||
ArenaPointer pointer = arena_alloc(arena, size, alignment);
|
||||
ArenaErr err = arena_ensure_capacity(arena, size, alignment);
|
||||
if (err != ARENA_OK) {
|
||||
ArenaPointer bad_pointer = {
|
||||
.is_valid = false,
|
||||
.err = err,
|
||||
};
|
||||
return bad_pointer;
|
||||
}
|
||||
|
||||
ArenaPointer pointer = arena_alloc(arena, size, alignment);
|
||||
if (!pointer.is_valid) {
|
||||
return pointer;
|
||||
}
|
||||
while (!pointer.is_valid && pointer.err == ARENA_OUT_OF_SPACE) {
|
||||
size_t new_capacity;
|
||||
|
||||
bool is_overflow = mul_size_t_safe(arena->capacity, 2, &new_capacity);
|
||||
if (is_overflow) {
|
||||
ArenaPointer bad_pointer = {
|
||||
.is_valid = false,
|
||||
.err = ARENA_CAPACITY_OVERFLOW,
|
||||
};
|
||||
return bad_pointer;
|
||||
}
|
||||
|
||||
ArenaErr err = arena_realloc(arena, new_capacity);
|
||||
if (err != ARENA_OK) {
|
||||
ArenaPointer bad_pointer = {
|
||||
.is_valid = false,
|
||||
.err = err,
|
||||
};
|
||||
return bad_pointer;
|
||||
}
|
||||
|
||||
pointer = arena_alloc(arena, size, alignment);
|
||||
}
|
||||
|
||||
|
||||
memcpy(
|
||||
pointer.address,
|
||||
data,
|
||||
@@ -143,7 +167,7 @@ ArenaErr arena_realloc(Arena *arena, size_t new_capacity) {
|
||||
return ARENA_OK;
|
||||
}
|
||||
|
||||
SizeResult align_arena_offset(Arena *arena, size_t alignment) {
|
||||
SizeResult get_arena_align_padding(Arena *arena, size_t alignment) {
|
||||
if (arena == NULL) {
|
||||
SizeResult err = {
|
||||
.is_valid = false,
|
||||
@@ -160,11 +184,11 @@ SizeResult align_arena_offset(Arena *arena, size_t alignment) {
|
||||
return err;
|
||||
}
|
||||
|
||||
uintptr_t current_address = (uintptr_t) (arena->buffer + arena->offset);
|
||||
uintptr_t aligned = ((current_address + (alignment - 1)) & ~(alignment - 1));
|
||||
SizeResult val = {
|
||||
.is_valid = true,
|
||||
.val = ((arena->offset + (alignment - 1)) & ~(alignment - 1)),
|
||||
// Formula for alignment, found at stackoverflow, i came up with one
|
||||
// but it involved 3 divisions, this one is way faster :)
|
||||
.val = aligned - current_address,
|
||||
};
|
||||
return val;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user