diff options
author | bonmas14 <bonmas14@gmail.com> | 2025-09-20 22:28:15 +0300 |
---|---|---|
committer | bonmas14 <bonmas14@gmail.com> | 2025-09-20 22:28:15 +0300 |
commit | cdda4c4182c9ee068567529715e4a5c68a8efb58 (patch) | |
tree | 38a63f62a64018a2d35fc33354f8589fd33b7514 /src/allocators.c | |
download | c_wizard-cdda4c4182c9ee068567529715e4a5c68a8efb58.tar.gz c_wizard-cdda4c4182c9ee068567529715e4a5c68a8efb58.zip |
Init commit v1.0
Diffstat (limited to 'src/allocators.c')
-rw-r--r-- | src/allocators.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/allocators.c b/src/allocators.c new file mode 100644 index 0000000..c3f2021 --- /dev/null +++ b/src/allocators.c @@ -0,0 +1,187 @@ +#include <stdlib.h> + +typedef enum { + ALLOCATOR_ALLOCATE, + ALLOCATOR_REALLOCATE, + ALLOCATOR_DEALLOCATE, + ALLOCATOR_DELETE +} Allocator_Message; + +#define ALLOCATOR_PROC(name)\ + void *name(void *p, u64 size, Allocator_Message message, void *data) + +typedef ALLOCATOR_PROC(Allocator_Proc); + +typedef struct { + Allocator_Proc *proc; + void *data; +} Allocator; + +#define mem_alloc(alloc, size) (alloc).proc(NULL, size, ALLOCATOR_ALLOCATE, (alloc).data) +#define mem_realloc(alloc, ptr, size) (alloc).proc(ptr, size, ALLOCATOR_REALLOCATE, (alloc).data) +#define mem_free(alloc, ptr) (alloc).proc(ptr, 0, ALLOCATOR_DEALLOCATE, (alloc).data) +#define mem_delete(alloc) (alloc).proc(NULL, 0, ALLOCATOR_DELETE, (alloc).data) + + +Allocator get_stdlib_allocator(void); +Allocator get_temporary_allocator(void); +Allocator create_arena_allocator(u64 size); + + +/// Stdlib Allocator +ALLOCATOR_PROC(stdlib_allocator_proc) { + UNUSED(data); + + switch (message) { + case ALLOCATOR_ALLOCATE: + return calloc(1, size); + case ALLOCATOR_REALLOCATE: + return realloc((u8*)p, size); + case ALLOCATOR_DEALLOCATE: + free((u8*)p); + break; + case ALLOCATOR_DELETE: + break; + } + + return NULL; +} + +Allocator get_stdlib_allocator(void) { + return CLITERAL(Allocator) { stdlib_allocator_proc, NULL }; +} + + +/// Temp Allocator + +#define TEMP_SIZE MB(50) + +struct { + b32 initialized; + u64 index; + u8 data[TEMP_SIZE]; +} __temp_alloc; + +void temp_reset(void) { + __temp_alloc.index = 0; +} + +void *temp_allocate(u64 size) { + if ((__temp_alloc.index + size) > TEMP_SIZE) { + TraceLog(LOG_ERROR, "Temp allocator wrapped!"); + temp_reset(); + } + + if ((__temp_alloc.index + size) > TEMP_SIZE) { + TraceLog(LOG_ERROR, "Too much space requested!"); + return NULL; + } + + + void *pos = (u8*)__temp_alloc.data + __temp_alloc.index; + __temp_alloc.index += size; + memset(pos, 0x00, size); + return pos; +} + +ALLOCATOR_PROC(temp_allocator_proc) { + UNUSED(data); + UNUSED(p); + + if (!__temp_alloc.initialized) { + __temp_alloc.initialized = true; + temp_reset(); + } + + switch (message) { + case ALLOCATOR_ALLOCATE: + return temp_allocate(size); + case ALLOCATOR_REALLOCATE: + case ALLOCATOR_DEALLOCATE: + break; + case ALLOCATOR_DELETE: + temp_reset(); + break; + } + + return NULL; +} + +Allocator get_temporary_allocator(void) { + return CLITERAL(Allocator) { temp_allocator_proc, NULL }; +} + +/// Arena allocator + +typedef struct Arena { + u64 size; + u64 occupied; + struct Arena *next; + u8 data[1]; // you dont have zero size arrays in MSVC... +} Arena; + +Arena *arena_create(u64 size) { + Allocator alloc = get_stdlib_allocator(); + + Arena *arena = (Arena *)mem_alloc(alloc, size); + + if (!arena) { + TraceLog(LOG_FATAL, "Buy mem, failed to create arena!"); + return NULL; + } + + memset(arena, 0, sizeof(Arena)); + arena->size = size - sizeof(Arena); + + return arena; +} + +void arena_delete(Arena *arena) { + if (arena->next != NULL) { + arena_delete(arena->next); + } + + Allocator alloc = get_stdlib_allocator(); + mem_free(alloc, arena); +} + +void *arena_allocate(u64 size, Arena *arena) { + if (size <= (arena->size - arena->occupied)) { + u8* pos = arena->data + arena->occupied; + arena->occupied += size; + return (void*)pos; + } + + if (!arena->next) { + arena->next = arena_create((arena->size + sizeof(Arena)) * 2LL); + } + + return arena_allocate(size, arena->next); +} + +ALLOCATOR_PROC(arena_allocator_proc) { + UNUSED(p); + assert(data != NULL); + + Arena *arena = (Arena*)data; + + switch (message) { + case ALLOCATOR_ALLOCATE: + return arena_allocate(size, arena); + case ALLOCATOR_REALLOCATE: + TraceLog(LOG_ERROR, "Arena doesn't reallocate."); + break; + case ALLOCATOR_DEALLOCATE: + TraceLog(LOG_ERROR, "Arena doesn't free it's memory, please destroy arena itself."); + break; + case ALLOCATOR_DELETE: + arena_delete(arena); + break; + } + + return NULL; +} + +Allocator create_arena_allocator(u64 size) { + return CLITERAL(Allocator) { arena_allocator_proc, arena_create(size) }; +} |