114 lines
2.7 KiB
C
114 lines
2.7 KiB
C
#include "mem_arena.h"
|
|
#include "aliases.h"
|
|
#include "mem_utils.h"
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifndef DEFAULT_ALIGNMENT
|
|
// Why 2 * sizeof(void *) instead of sizeof(void *)
|
|
// https://handmade.network/forums/t/6860-alignment_arena_allocator
|
|
#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
|
|
#endif /* ifndef DEFAULT_ALIGNMENT */
|
|
|
|
#define ARENA_MINIMUM_CAPACITY 1024
|
|
|
|
struct arena {
|
|
u8 *buf;
|
|
u8 *offset;
|
|
u64 capacity;
|
|
bool committed;
|
|
};
|
|
|
|
// PUBLIC API
|
|
|
|
bool wapp_mem_arena_init(Arena **arena, u64 base_capacity, MemAllocFlags flags,
|
|
bool zero_buffer) {
|
|
if (!arena || *arena || base_capacity == 0) {
|
|
return false;
|
|
}
|
|
|
|
*arena = (Arena *)calloc(1, sizeof(Arena));
|
|
Arena *arena_ptr = *arena;
|
|
if (!arena_ptr) {
|
|
return false;
|
|
}
|
|
|
|
u64 arena_capacity = base_capacity >= ARENA_MINIMUM_CAPACITY
|
|
? base_capacity
|
|
: ARENA_MINIMUM_CAPACITY;
|
|
|
|
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(
|
|
NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
|
|
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
|
|
|
|
if (!(arena_ptr->buf)) {
|
|
wapp_mem_arena_destroy(arena);
|
|
return false;
|
|
}
|
|
|
|
arena_ptr->capacity = arena_capacity;
|
|
arena_ptr->offset = arena_ptr->buf;
|
|
arena_ptr->committed =
|
|
(flags & WAPP_MEM_ALLOC_COMMIT) == WAPP_MEM_ALLOC_COMMIT;
|
|
|
|
return true;
|
|
}
|
|
|
|
void *wapp_mem_arena_alloc(Arena *arena, u64 size) {
|
|
return wapp_mem_arena_alloc_aligned(arena, size, DEFAULT_ALIGNMENT);
|
|
}
|
|
|
|
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
|
if (!arena) {
|
|
return NULL;
|
|
}
|
|
|
|
u8 *alloc_start = arena->offset;
|
|
|
|
u8 *output = wapp_mem_util_align_forward((void *)alloc_start, alignment);
|
|
if (output + size >= arena->buf + arena->capacity) {
|
|
return NULL;
|
|
}
|
|
|
|
arena->offset = output + size;
|
|
|
|
#ifdef WAPP_PLATFORM_WINDOWS
|
|
if (!(arena->committed)) {
|
|
output = (u8 *)wapp_mem_util_alloc(output, size, WAPP_MEM_ACCESS_READ_WRITE,
|
|
WAPP_MEM_ALLOC_COMMIT,
|
|
WAPP_MEM_INIT_UNINITIALISED);
|
|
}
|
|
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
|
|
|
memset(output, 0, size);
|
|
|
|
return (void *)output;
|
|
}
|
|
|
|
void wapp_mem_arena_clear(Arena *arena) {
|
|
if (!arena) {
|
|
return;
|
|
}
|
|
|
|
memset(arena->buf, 0, arena->offset - arena->buf);
|
|
arena->offset = arena->buf;
|
|
}
|
|
|
|
void wapp_mem_arena_destroy(Arena **arena) {
|
|
if (!arena) {
|
|
return;
|
|
}
|
|
|
|
Arena *arena_ptr = *arena;
|
|
if (arena_ptr->buf) {
|
|
wapp_mem_util_free(arena_ptr->buf, arena_ptr->capacity);
|
|
}
|
|
|
|
arena_ptr->buf = arena_ptr->offset = NULL;
|
|
arena_ptr->capacity = 0;
|
|
|
|
free(*arena);
|
|
*arena = NULL;
|
|
}
|