test/refactor: lock approach taken, best one
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user