From 2dcef95b2e1b871f615b015eadbb6695596be2fc Mon Sep 17 00:00:00 2001 From: laentropia Date: Sat, 6 Jun 2026 09:48:18 -0600 Subject: [PATCH] refactor: arena uses Allocator --- include/lae_arena.h | 29 +++++------- src/lae_arena.c | 33 ++++++++----- test/test_arena.c | 111 +++++++++++++++++++++++++------------------- xmake.lua | 11 +++-- 4 files changed, 101 insertions(+), 83 deletions(-) diff --git a/include/lae_arena.h b/include/lae_arena.h index 8a9f786..b9f7bf3 100644 --- a/include/lae_arena.h +++ b/include/lae_arena.h @@ -1,6 +1,7 @@ #ifndef LAE_ARENA_H #define LAE_ARENA_H +#include "lae_allocator.h" #include #include #include @@ -23,7 +24,7 @@ typedef struct { union { ArenaErr err; struct { - Arena* arena; + Arena *arena; size_t offset; }; }; @@ -33,32 +34,24 @@ typedef struct { bool is_valid; union { ArenaErr err; - Arena* arena; - }; -} ArenaResult; - -typedef struct { - bool is_valid; - union { - ArenaErr err; - size_t val; + size_t val; }; } ArenaSizeResult; -ArenaErr arena_init(Arena** arena, size_t capacity); -ArenaErr arena_destroy(Arena** arena); +ArenaErr arena_init(Arena **arena, Allocator allocator, size_t capacity); +ArenaErr arena_destroy(Arena **arena); -ArenaPointer arena_alloc(Arena* arena, size_t size, size_t alignment); +ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment); ArenaPointer - arena_push(Arena* arena, void* data, size_t size, size_t alignment); -ArenaErr arena_realloc(Arena* arena, size_t new_capacity); -void* arena_unwrap_pointer(ArenaPointer p); +arena_push_data(Arena *arena, void *data, size_t size, size_t alignment); +ArenaErr arena_resize(Arena *arena, size_t new_capacity); +void *arena_unwrap_pointer(ArenaPointer p); -ArenaSizeResult arena_get_align_padding(Arena* arena, size_t alignment); +ArenaSizeResult arena_get_align_padding(Arena *arena, size_t alignment); // can take big sizes but of sourse there is a limit, // its protected against SIZE_MAX but anything that // is big may break it, still, is an edge case that // I shouldn't cover. -ArenaErr arena_ensure_capacity(Arena* arena, size_t size, size_t alignment); +ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment); #endif // !RENA_H diff --git a/src/lae_arena.c b/src/lae_arena.c index 559dec2..0d08a25 100644 --- a/src/lae_arena.c +++ b/src/lae_arena.c @@ -10,9 +10,11 @@ struct Arena { uint8_t *buffer; size_t capacity; size_t offset; + + Allocator allocator; }; -ArenaErr arena_init(Arena **arena, size_t capacity) { +ArenaErr arena_init(Arena **arena, Allocator allocator, size_t capacity) { if (arena == NULL) { return ARENA_NULL_ARG; } @@ -21,13 +23,14 @@ ArenaErr arena_init(Arena **arena, size_t capacity) { return ARENA_INVALID_SIZE; } - Arena *new_arena = malloc(sizeof(Arena)); + Arena *new_arena = allocator.alloc(allocator.ctx, sizeof(Arena)); if (new_arena == NULL) { return ARENA_BAD_ALLOC; } - void *buffer = malloc(capacity); + void *buffer = allocator.alloc(allocator.ctx, capacity); if (buffer == NULL) { + allocator.free(allocator.ctx, new_arena, capacity); return ARENA_BAD_ALLOC; } @@ -35,6 +38,7 @@ ArenaErr arena_init(Arena **arena, size_t capacity) { .buffer = buffer, .capacity = capacity, .offset = 0, + .allocator = allocator, }; *arena = new_arena; @@ -47,11 +51,12 @@ ArenaErr arena_destroy(Arena **arena) { return ARENA_NULL_ARG; } - free((*arena)->buffer); - (*arena)->buffer = NULL; - (*arena)->offset = 0; - (*arena)->capacity = 0; - free(*arena); + Arena *tmp = *arena; + tmp->allocator.free(tmp->allocator.ctx, tmp->buffer, tmp->capacity); + tmp->buffer = NULL; + tmp->offset = 0; + tmp->capacity = 0; + tmp->allocator.free(tmp->allocator.ctx, *arena, sizeof(Arena)); *arena = NULL; return ARENA_OK; @@ -146,7 +151,7 @@ ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment) { new_capacity = required; } - ArenaErr err = arena_realloc(arena, new_capacity); + ArenaErr err = arena_resize(arena, new_capacity); if (err != ARENA_OK) { return err; } @@ -154,7 +159,7 @@ ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment) { } ArenaPointer -arena_push(Arena *arena, void *data, size_t size, size_t alignment) { +arena_push_data(Arena *arena, void *data, size_t size, size_t alignment) { if (arena == NULL || data == NULL) { return (ArenaPointer){.is_valid = false, .err = ARENA_NULL_ARG}; } @@ -182,7 +187,7 @@ arena_push(Arena *arena, void *data, size_t size, size_t alignment) { return pointer; } -ArenaErr arena_realloc(Arena *arena, size_t new_capacity) { +ArenaErr arena_resize(Arena *arena, size_t new_capacity) { if (arena == NULL) { return ARENA_NULL_ARG; } @@ -191,7 +196,11 @@ ArenaErr arena_realloc(Arena *arena, size_t new_capacity) { return ARENA_INVALID_SIZE; } - uint8_t *tmp = realloc(arena->buffer, new_capacity); + uint8_t *tmp = arena->allocator.realloc( + arena->allocator.ctx, + arena->buffer, + arena->capacity, + new_capacity); if (tmp == NULL) { return ARENA_BAD_ALLOC; } diff --git a/test/test_arena.c b/test/test_arena.c index 1d86f8b..63e84bb 100644 --- a/test/test_arena.c +++ b/test/test_arena.c @@ -1,90 +1,106 @@ +#include +#include +#include #include -#include #include #include #include #include -#include -#include #include -#include +#include "lae_allocator.h" #include "lae_arena.h" static void test_push_3_ints(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, sizeof(int) * 3), ARENA_OK); + assert_uint_equal( + arena_init(&arena, allocator_default(), sizeof(int) * 3), + ARENA_OK); int int_to_push = 20; - ArenaPointer result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); + ArenaPointer result = + arena_push_data(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); - assert_int_equal(20, *(int*)arena_unwrap_pointer(result)); - assert_int_equal(20, *(int*)arena_unwrap_pointer(result)); + assert_int_equal(20, *(int *)arena_unwrap_pointer(result)); + assert_int_equal(20, *(int *)arena_unwrap_pointer(result)); int_to_push = 30; - result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push_data(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); - assert_int_equal(30, *(int*)arena_unwrap_pointer(result)); + assert_int_equal(30, *(int *)arena_unwrap_pointer(result)); int_to_push = 40; - result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push_data(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); - assert_int_equal(40, *(int*)arena_unwrap_pointer(result)); + assert_int_equal(40, *(int *)arena_unwrap_pointer(result)); arena_destroy(&arena); } static void test_push_3_ints_2_doubles(void **state) { - (void) state; + (void)state; Arena *arena; assert_uint_equal( - arena_init(&arena, (sizeof(int) * 3) + (sizeof(double) * 2)), - ARENA_OK - ); + arena_init( + &arena, + allocator_default(), + (sizeof(int) * 3) + (sizeof(double) * 2)), + ARENA_OK); int int_to_push = 20; - ArenaPointer result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); + ArenaPointer result = + arena_push_data(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); - assert_int_equal(20, *(int*)arena_unwrap_pointer(result)); + assert_int_equal(20, *(int *)arena_unwrap_pointer(result)); double double_to_push = 4.57; - result = arena_push(arena, &double_to_push, sizeof(double), alignof(double)); + result = arena_push_data( + arena, + &double_to_push, + sizeof(double), + alignof(double)); assert_true(result.is_valid); - assert_double_equal(4.57, *(double*)arena_unwrap_pointer(result), 1e-6); + assert_double_equal(4.57, *(double *)arena_unwrap_pointer(result), 1e-6); int_to_push = 30; - result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push_data(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); - assert_int_equal(30, *(int*)arena_unwrap_pointer(result)); + assert_int_equal(30, *(int *)arena_unwrap_pointer(result)); int_to_push = 40; - result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push_data(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); - assert_int_equal(40, *(int*)arena_unwrap_pointer(result)); + assert_int_equal(40, *(int *)arena_unwrap_pointer(result)); double_to_push = 267.33; - result = arena_push(arena, &double_to_push, sizeof(double), alignof(double)); + result = arena_push_data( + arena, + &double_to_push, + sizeof(double), + alignof(double)); assert_true(result.is_valid); - assert_double_equal(267.33, *(double*)arena_unwrap_pointer(result), 1e-6); + assert_double_equal(267.33, *(double *)arena_unwrap_pointer(result), 1e-6); arena_destroy(&arena); } static void test_init_arena_0_cap(void **state) { - (void) state; + (void)state; Arena *arena; - assert_int_equal(arena_init(&arena, 0), ARENA_INVALID_SIZE); + assert_int_equal( + arena_init(&arena, allocator_default(), 0), + ARENA_INVALID_SIZE); } static void test_arena_alloc_size_0(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaPointer pointer = arena_alloc(arena, 0, alignof(int)); assert_false(pointer.is_valid); @@ -94,10 +110,10 @@ static void test_arena_alloc_size_0(void **state) { } static void test_arena_alloc_size_max(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaPointer pointer = arena_alloc(arena, SIZE_MAX, alignof(int)); assert_false(pointer.is_valid); @@ -107,10 +123,10 @@ static void test_arena_alloc_size_max(void **state) { } static void test_arena_alloc_align_0(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaPointer pointer = arena_alloc(arena, sizeof(int), 0); assert_false(pointer.is_valid); @@ -120,10 +136,10 @@ static void test_arena_alloc_align_0(void **state) { } static void test_arena_alloc_align_max(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaPointer pointer = arena_alloc(arena, sizeof(int), SIZE_MAX); assert_false(pointer.is_valid); @@ -133,10 +149,10 @@ static void test_arena_alloc_align_max(void **state) { } static void test_arena_align_size_0(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaPointer pointer = arena_alloc(arena, sizeof(int), 0); assert_false(pointer.is_valid); @@ -146,10 +162,10 @@ static void test_arena_align_size_0(void **state) { } static void test_arena_ensure_capacity_size_0(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaErr err = arena_ensure_capacity(arena, 0, alignof(int)); assert_int_equal(err, ARENA_INVALID_SIZE); @@ -158,10 +174,10 @@ static void test_arena_ensure_capacity_size_0(void **state) { } static void test_arena_ensure_capacity_size_max(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaErr err = arena_ensure_capacity(arena, SIZE_MAX, alignof(int)); assert_int_equal(err, ARENA_INVALID_SIZE); @@ -170,10 +186,10 @@ static void test_arena_ensure_capacity_size_max(void **state) { } static void test_arena_ensure_capacity_align_0(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaErr err = arena_ensure_capacity(arena, sizeof(int), 0); assert_int_equal(err, ARENA_INVALID_ALIGN); @@ -182,10 +198,10 @@ static void test_arena_ensure_capacity_align_0(void **state) { } static void test_arena_ensure_capacity_align_max(void **state) { - (void) state; + (void)state; Arena *arena; - assert_uint_equal(arena_init(&arena, 64), ARENA_OK); + assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK); ArenaErr err = arena_ensure_capacity(arena, sizeof(int), SIZE_MAX); assert_int_equal(err, ARENA_INVALID_ALIGN); @@ -209,6 +225,5 @@ int main(void) { cmocka_unit_test(test_arena_ensure_capacity_size_max), }; - return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/xmake.lua b/xmake.lua index 67afb3b..34b97f0 100644 --- a/xmake.lua +++ b/xmake.lua @@ -44,7 +44,7 @@ add_requires("lae_allocator") target("lae_arena") set_kind("static") -add_packages("lae_allocator") +add_packages("lae_allocator", { public = true }) add_files("src/lae_arena.c") @@ -64,9 +64,10 @@ if has_config("example") then target("example") set_kind("binary") - add_files("src/main.c") - add_deps("lae_arena") + add_packages("lae_allocator") + + add_files("src/main.c") end -- ========================================================= @@ -77,12 +78,12 @@ if has_config("tests") then target("test_arena") set_kind("binary") - add_files("test/test_arena.c") - add_deps("lae_arena") add_packages("cmocka") + add_files("test/test_arena.c") + add_tests("default") if has_config("asan") then