Files
nob/src/mini_arena.h
T
Nils O. Selåsdal 0fbe5e8255 Shorter names
2026-06-10 20:23:14 +02:00

97 lines
2.4 KiB
C

#pragma once
#include "base_core.h"
// Mini Arena for arena allocations from a supplied buffer
typedef struct MArena MArena;
struct MArena {
U8 *base; // start of buffer
U32 first_free;
U32 size;
S32 temp_level; // level of marena_temp_begin nesting
};
typedef struct MTemp MTemp;
struct MTemp {
U32 offset;
MArena *arena;
};
#define MARENA_STATIC_INITIALIZER(data) MARENA_INITIALIZER((data), sizeof(data))
#define MARENA_INITIALIZER(data, size_) {.base = (data), .first_free = 0, .size = (U32)size_, .temp_level = 0}
#define MARENA_DEFINE(var_name, size, alignment_) \
struct { \
_Alignas(alignment_) U8 memory[size];\
} var_name##_marena_memory; \
MArena var_name = MARENA_STATIC_INITIALIZER(var_name##_marena_memory.memory)
static INLINE void marena_init(MArena *arena, void *memory, U32 size)
{
Assert(memory != NULL);
arena->base = (U8 *)memory;
arena->first_free = 0;
arena->size = size;
}
static INLINE MTemp marena_temp_begin(MArena *arena)
{
MTemp checkpoint = {};
checkpoint.arena = arena;
checkpoint.offset = arena->first_free;
arena->temp_level++;
return checkpoint;
}
static INLINE void marena_temp_end(MTemp *state)
{
MArena *arena = state->arena;
Assert(arena->temp_level > 0);
arena->first_free = state->offset;
arena->temp_level--;
}
#define marena_push_type(allocator, type_)\
marenaalloc_aligned((allocator), sizeof(type_), _Alignof(type_))
#define marena_push_array(allocator, type_, nr_elements_)\
marenaalloc_aligned((allocator), (nr_elements_) * (U32)sizeof(type_), _Alignof(type_))
static INLINE void *marena_push(MArena *arena, U32 size)
{
if (size > arena->size - arena->first_free) {
return NULL;
}
void *base = &arena->base[arena->first_free];
arena->first_free += size;
return base;
}
[[gnu::alloc_align(3)]]
static INLINE void *maren_push_aligned(MArena *arena, U32 size, U32 align)
{
Assert(IsPow2(align));
U32 aligned = AlignUp(arena->first_free, align);
if (aligned < arena->first_free) { // aligned wrapped around
return NULL;
}
if (aligned > arena->size || size > arena->size - aligned) {
return NULL;
}
void *base = &arena->base[aligned];
arena->first_free = aligned + size;
return base;
}
static INLINE void marena_reset(MArena *arena)
{
arena->first_free = 0;
}