Add temp arena support
This commit is contained in:
@@ -24,11 +24,12 @@ typedef enum {
|
||||
struct Arena {
|
||||
u8 *buf;
|
||||
u8 *offset;
|
||||
u8 *prev_offset;
|
||||
u64 capacity;
|
||||
ArenaStorageType type;
|
||||
b8 committed;
|
||||
|
||||
wapp_misc_utils_reserve_padding(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(ArenaStorageType) + sizeof(b8));
|
||||
wapp_misc_utils_reserve_padding(sizeof(u8 *) * 3 + sizeof(u64) + sizeof(ArenaStorageType) + sizeof(b8));
|
||||
};
|
||||
|
||||
b8 wapp_mem_arena_init_buffer(Arena **arena, u8 *buffer, u64 buffer_size) {
|
||||
@@ -39,11 +40,12 @@ b8 wapp_mem_arena_init_buffer(Arena **arena, u8 *buffer, u64 buffer_size) {
|
||||
*arena = (Arena *)buffer;
|
||||
Arena *arena_ptr = *arena;
|
||||
|
||||
arena_ptr->buf = (u8 *)(arena_ptr + 1);
|
||||
arena_ptr->offset = arena_ptr->buf;
|
||||
arena_ptr->capacity = buffer_size - sizeof(Arena);
|
||||
arena_ptr->type = ARENA_STORAGE_TYPE_BUFFER;
|
||||
arena_ptr->committed = true;
|
||||
arena_ptr->buf = (u8 *)(arena_ptr + 1);
|
||||
arena_ptr->offset = arena_ptr->buf;
|
||||
arena_ptr->prev_offset = NULL;
|
||||
arena_ptr->capacity = buffer_size - sizeof(Arena);
|
||||
arena_ptr->type = ARENA_STORAGE_TYPE_BUFFER;
|
||||
arena_ptr->committed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -112,6 +114,8 @@ void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||
return NULL;
|
||||
@@ -129,6 +133,8 @@ void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64 new_size, u64 alignment) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||
return NULL;
|
||||
@@ -145,6 +151,27 @@ void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_temp_begin(Arena *arena) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
if (arena->prev_offset != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
arena->prev_offset = arena->offset;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_temp_end(Arena *arena) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
if (arena->prev_offset == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
arena->offset = arena->prev_offset;
|
||||
arena->prev_offset = NULL;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_clear(Arena *arena) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ void *wapp_mem_arena_alloc(Arena *arena, u64 size);
|
||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment);
|
||||
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size);
|
||||
void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64 new_size, u64 alignment);
|
||||
void wapp_mem_arena_temp_begin(Arena *arena);
|
||||
void wapp_mem_arena_temp_end(Arena *arena);
|
||||
void wapp_mem_arena_clear(Arena *arena);
|
||||
void wapp_mem_arena_destroy(Arena **arena);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "mem_arena.h"
|
||||
#include "../../mem/mem_os.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/assert/assert.h"
|
||||
|
||||
wapp_intern void initialise_arena_allocator(Allocator *allocator);
|
||||
wapp_intern void *mem_arena_alloc(u64 size, void *alloc_obj);
|
||||
@@ -36,11 +37,23 @@ Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags
|
||||
return allocator;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_temp_begin(const Allocator *allocator) {
|
||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||
wapp_mem_arena_temp_begin((Arena *)(allocator->obj));
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_temp_end(const Allocator *allocator) {
|
||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||
wapp_mem_arena_temp_end((Arena *)(allocator->obj));
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_clear(Allocator *allocator) {
|
||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||
wapp_mem_arena_clear((Arena *)(allocator->obj));
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
|
||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||
wapp_mem_arena_destroy((Arena **)(&(allocator->obj)));
|
||||
*allocator = (Allocator){0};
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ BEGIN_C_LINKAGE
|
||||
*/
|
||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b8 zero_buffer);
|
||||
Allocator wapp_mem_arena_allocator_init_with_buffer(u8 *buffer, u64 buffer_size);
|
||||
void wapp_mem_arena_allocator_temp_begin(const Allocator *allocator);
|
||||
void wapp_mem_arena_allocator_temp_end(const Allocator *allocator);
|
||||
void wapp_mem_arena_allocator_clear(Allocator *allocator);
|
||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
#include "wapp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||
|
||||
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {0};
|
||||
wapp_intern Allocator temp_allocator = {0};
|
||||
|
||||
TestFuncResult test_arena_allocator(void) {
|
||||
Allocator allocator = wapp_mem_arena_allocator_init(4096);
|
||||
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
|
||||
@@ -31,3 +38,30 @@ TestFuncResult test_arena_allocator_with_buffer(void) {
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_allocator_temp_begin(void) {
|
||||
temp_allocator = wapp_mem_arena_allocator_init_with_buffer(temp_buf, TEMP_BUF_SIZE);
|
||||
|
||||
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
b8 result = num1 != NULL;
|
||||
|
||||
wapp_mem_arena_allocator_temp_begin(&temp_allocator);
|
||||
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
result = result && num2 != NULL;
|
||||
i32 *num3 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
result = result && num3 == NULL;
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_allocator_temp_end(void) {
|
||||
wapp_mem_arena_allocator_temp_end(&temp_allocator);
|
||||
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
b8 result = num1 != NULL;
|
||||
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
result = result && num2 == NULL;
|
||||
|
||||
wapp_mem_arena_allocator_destroy(&temp_allocator);
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
#include "wapp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||
|
||||
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {};
|
||||
wapp_intern Allocator temp_allocator = {};
|
||||
|
||||
TestFuncResult test_arena_allocator(void) {
|
||||
Allocator allocator = wapp_mem_arena_allocator_init(4096);
|
||||
b8 result = allocator.obj != nullptr && allocator.alloc != nullptr &&
|
||||
@@ -31,3 +38,30 @@ TestFuncResult test_arena_allocator_with_buffer(void) {
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_allocator_temp_begin(void) {
|
||||
temp_allocator = wapp_mem_arena_allocator_init_with_buffer(temp_buf, TEMP_BUF_SIZE);
|
||||
|
||||
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
b8 result = num1 != NULL;
|
||||
|
||||
wapp_mem_arena_allocator_temp_begin(&temp_allocator);
|
||||
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
result = result && num2 != NULL;
|
||||
i32 *num3 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
result = result && num3 == NULL;
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_allocator_temp_end(void) {
|
||||
wapp_mem_arena_allocator_temp_end(&temp_allocator);
|
||||
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
b8 result = num1 != NULL;
|
||||
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||
result = result && num2 == NULL;
|
||||
|
||||
wapp_mem_arena_allocator_destroy(&temp_allocator);
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
@@ -5,5 +5,7 @@
|
||||
|
||||
TestFuncResult test_arena_allocator(void);
|
||||
TestFuncResult test_arena_allocator_with_buffer(void);
|
||||
TestFuncResult test_arena_allocator_temp_begin(void);
|
||||
TestFuncResult test_arena_allocator_temp_end(void);
|
||||
|
||||
#endif // !TEST_ALLOCATOR_H
|
||||
|
||||
@@ -4,12 +4,17 @@
|
||||
|
||||
#define ARENA_CAPACITY KiB(16)
|
||||
#define ARENA_BUF_SIZE KiB(4)
|
||||
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||
|
||||
wapp_intern Arena *arena = NULL;
|
||||
wapp_intern i32 count = 20;
|
||||
wapp_intern i32 *array = NULL;
|
||||
wapp_intern Arena *buf_arena = NULL;
|
||||
wapp_intern u8 buf[ARENA_BUF_SIZE] = {0};
|
||||
wapp_intern Arena *arena = NULL;
|
||||
wapp_intern i32 count = 20;
|
||||
wapp_intern i32 *array = NULL;
|
||||
wapp_intern Arena *buf_arena = NULL;
|
||||
wapp_intern u8 buf[ARENA_BUF_SIZE] = {0};
|
||||
wapp_intern Arena *temp_arena = NULL;
|
||||
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {0};
|
||||
|
||||
TestFuncResult test_arena_init_buffer(void) {
|
||||
b8 result = wapp_mem_arena_init_buffer(&buf_arena, buf, ARENA_BUF_SIZE);
|
||||
@@ -108,6 +113,32 @@ TestFuncResult test_arena_realloc_smaller_size(void) {
|
||||
return wapp_tester_result(true);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_temp_begin(void) {
|
||||
b8 result = wapp_mem_arena_init_buffer(&temp_arena, temp_buf, TEMP_BUF_SIZE);
|
||||
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num1 != NULL;
|
||||
|
||||
wapp_mem_arena_temp_begin(temp_arena);
|
||||
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num2 != NULL;
|
||||
i32 *num3 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num3 == NULL;
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_temp_end(void) {
|
||||
wapp_mem_arena_temp_end(temp_arena);
|
||||
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
b8 result = num1 != NULL;
|
||||
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num2 == NULL;
|
||||
|
||||
wapp_mem_arena_destroy(&temp_arena);
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_clear(void) {
|
||||
wapp_mem_arena_clear(arena);
|
||||
b8 result = true;
|
||||
|
||||
@@ -4,12 +4,17 @@
|
||||
|
||||
#define ARENA_CAPACITY KiB(16)
|
||||
#define ARENA_BUF_SIZE KiB(4)
|
||||
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||
|
||||
wapp_intern Arena *arena = NULL;
|
||||
wapp_intern i32 count = 20;
|
||||
wapp_intern i32 *array = NULL;
|
||||
wapp_intern Arena *buf_arena = NULL;
|
||||
wapp_intern u8 buf[ARENA_BUF_SIZE] = {0};
|
||||
wapp_intern Arena *arena = NULL;
|
||||
wapp_intern i32 count = 20;
|
||||
wapp_intern i32 *array = NULL;
|
||||
wapp_intern Arena *buf_arena = NULL;
|
||||
wapp_intern u8 buf[ARENA_BUF_SIZE] = {};
|
||||
wapp_intern Arena *temp_arena = NULL;
|
||||
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {};
|
||||
|
||||
TestFuncResult test_arena_init_buffer(void) {
|
||||
b8 result = wapp_mem_arena_init_buffer(&buf_arena, buf, ARENA_BUF_SIZE);
|
||||
@@ -108,6 +113,32 @@ TestFuncResult test_arena_realloc_smaller_size(void) {
|
||||
return wapp_tester_result(true);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_temp_begin(void) {
|
||||
b8 result = wapp_mem_arena_init_buffer(&temp_arena, temp_buf, TEMP_BUF_SIZE);
|
||||
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num1 != NULL;
|
||||
|
||||
wapp_mem_arena_temp_begin(temp_arena);
|
||||
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num2 != NULL;
|
||||
i32 *num3 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num3 == NULL;
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_temp_end(void) {
|
||||
wapp_mem_arena_temp_end(temp_arena);
|
||||
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
b8 result = num1 != NULL;
|
||||
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||
result = result && num2 == NULL;
|
||||
|
||||
wapp_mem_arena_destroy(&temp_arena);
|
||||
|
||||
return wapp_tester_result(result);
|
||||
}
|
||||
|
||||
TestFuncResult test_arena_clear(void) {
|
||||
wapp_mem_arena_clear(arena);
|
||||
b8 result = true;
|
||||
|
||||
@@ -12,6 +12,8 @@ TestFuncResult test_arena_alloc_fails_when_over_capacity(void);
|
||||
TestFuncResult test_arena_realloc_bigger_size(void);
|
||||
TestFuncResult test_arena_realloc_smaller_size(void);
|
||||
TestFuncResult test_arena_clear(void);
|
||||
TestFuncResult test_arena_temp_begin(void);
|
||||
TestFuncResult test_arena_temp_end(void);
|
||||
TestFuncResult test_arena_destroy_buffer(void);
|
||||
TestFuncResult test_arena_destroy_allocated(void);
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ int main(void) {
|
||||
wapp_tester_run_tests(
|
||||
test_arena_allocator,
|
||||
test_arena_allocator_with_buffer,
|
||||
test_arena_allocator_temp_begin,
|
||||
test_arena_allocator_temp_end,
|
||||
test_arena_init_buffer,
|
||||
test_arena_init_allocated,
|
||||
test_arena_init_succeeds_when_reserving_very_large_size,
|
||||
@@ -22,6 +24,8 @@ int main(void) {
|
||||
test_arena_alloc_fails_when_over_capacity,
|
||||
test_arena_realloc_bigger_size,
|
||||
test_arena_realloc_smaller_size,
|
||||
test_arena_temp_begin,
|
||||
test_arena_temp_end,
|
||||
test_arena_clear,
|
||||
test_arena_destroy_buffer,
|
||||
test_arena_destroy_allocated,
|
||||
|
||||
@@ -14,6 +14,8 @@ int main(void) {
|
||||
wapp_tester_run_tests(
|
||||
test_arena_allocator,
|
||||
test_arena_allocator_with_buffer,
|
||||
test_arena_allocator_temp_begin,
|
||||
test_arena_allocator_temp_end,
|
||||
test_arena_init_buffer,
|
||||
test_arena_init_allocated,
|
||||
test_arena_init_succeeds_when_reserving_very_large_size,
|
||||
@@ -22,6 +24,8 @@ int main(void) {
|
||||
test_arena_alloc_fails_when_over_capacity,
|
||||
test_arena_realloc_bigger_size,
|
||||
test_arena_realloc_smaller_size,
|
||||
test_arena_temp_begin,
|
||||
test_arena_temp_end,
|
||||
test_arena_clear,
|
||||
test_arena_destroy_buffer,
|
||||
test_arena_destroy_allocated,
|
||||
|
||||
Reference in New Issue
Block a user