test/refactor: lock approach taken, best one

This commit is contained in:
2026-06-10 10:21:43 -06:00
parent 73dc05bc63
commit 0af6a0f104
3 changed files with 90 additions and 5 deletions

View File

@@ -17,6 +17,7 @@ typedef enum {
ARENA_INVALID_SIZE,
ARENA_INVALID_ALIGN,
ARENA_CAPACITY_OVERFLOW,
ARENA_LOCKED,
} ArenaErr;
typedef struct {
@@ -37,7 +38,7 @@ typedef struct {
ArenaErr err;
Allocator allocator;
};
} ArenaAllocResult;
} ArenaAllocator;
typedef struct {
bool is_valid;
@@ -63,6 +64,9 @@ ArenaSizeResult arena_get_align_padding(Arena *arena, size_t alignment);
// I shouldn't cover.
ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment);
ArenaAllocResult arena_get_allocator(Arena *arena);
ArenaErr arena_lock_growth(Arena *arena);
ArenaErr arena_unlock_growth(Arena *arena);
ArenaAllocator arena_get_allocator(Arena *arena);
#endif // !RENA_H

View File

@@ -12,6 +12,7 @@ struct Arena {
size_t capacity;
size_t offset;
bool growth_locked;
Allocator allocator;
};
@@ -50,6 +51,7 @@ ArenaErr arena_init(Arena **arena, Allocator allocator, size_t capacity) {
.buffer = buffer,
.capacity = capacity,
.offset = 0,
.growth_locked = false,
.allocator = allocator,
};
@@ -68,6 +70,7 @@ ArenaErr arena_destroy(Arena **arena) {
tmp->buffer = NULL;
tmp->offset = 0;
tmp->capacity = 0;
tmp->growth_locked = false;
tmp->allocator
.free(tmp->allocator.ctx, *arena, sizeof(Arena), alignof(Arena));
*arena = NULL;
@@ -209,6 +212,10 @@ ArenaErr arena_resize(Arena *arena, size_t new_capacity) {
return ARENA_INVALID_SIZE;
}
if (arena->growth_locked) {
return ARENA_LOCKED;
}
uint8_t *tmp = arena->allocator.realloc(
arena->allocator.ctx,
arena->buffer,
@@ -241,6 +248,24 @@ ArenaSizeResult arena_get_align_padding(Arena *arena, size_t alignment) {
return (ArenaSizeResult){.is_valid = true, .val = padding};
}
ArenaErr arena_lock_growth(Arena *arena) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
arena->growth_locked = true;
return ARENA_OK;
}
ArenaErr arena_unlock_growth(Arena *arena) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
arena->growth_locked = false;
return ARENA_OK;
}
void *arena_unwrap_pointer(ArenaPointer p) {
if (!p.is_valid) {
return NULL;
@@ -268,19 +293,21 @@ arena_allocator_free(void *ctx, void *pointer, size_t size, size_t alignment) {
return;
}
ArenaAllocResult arena_get_allocator(Arena *arena) {
ArenaAllocator arena_get_allocator(Arena *arena) {
if (arena == NULL) {
return (ArenaAllocResult){
return (ArenaAllocator){
.is_valid = false,
.err = ARENA_NULL_ARG,
};
}
arena->growth_locked = true;
Allocator allocator = {
.alloc = arena_allocator_alloc,
.realloc = arena_allocator_realloc,
.free = arena_allocator_free,
.ctx = arena};
return (ArenaAllocResult){.is_valid = true, .allocator = allocator};
return (ArenaAllocator){.is_valid = true, .allocator = allocator};
}

View File

@@ -209,6 +209,59 @@ static void test_arena_ensure_capacity_align_max(void **state) {
arena_destroy(&arena);
}
static void test_arena_allocator_valid_allocation(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaAllocator result = arena_get_allocator(arena);
assert_true(result.is_valid);
Allocator arena_allocator = result.allocator;
int *x =
arena_allocator.alloc(arena_allocator.ctx, sizeof(int), alignof(int));
assert_non_null(x);
*x = 34;
assert_int_equal(*x, 34);
arena_destroy(&arena);
}
static void test_arena_allocatro_many_allocations(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaAllocator result = arena_get_allocator(arena);
assert_true(result.is_valid);
Allocator arena_allocator = result.allocator;
for (int i = 0; i < 10; i++) {
int *x = arena_allocator.alloc(
arena_allocator.ctx,
sizeof(int),
alignof(int));
assert_non_null(x);
}
arena_destroy(&arena);
}
static void test_arena_allocator_from_null_arena(void **state) {
(void)state;
Arena *arena = NULL;
ArenaAllocator result = arena_get_allocator(arena);
assert_false(result.is_valid);
}
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_push_3_ints),
@@ -223,6 +276,7 @@ int main(void) {
cmocka_unit_test(test_arena_ensure_capacity_align_max),
cmocka_unit_test(test_arena_ensure_capacity_size_0),
cmocka_unit_test(test_arena_ensure_capacity_size_max),
cmocka_unit_test(test_arena_allocator_valid_allocation),
};
return cmocka_run_group_tests(tests, NULL, NULL);