Start mini arena
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "base_core.h"
|
||||||
|
|
||||||
|
typedef struct MiniArena MiniArena;
|
||||||
|
struct MiniArena {
|
||||||
|
U8 *start; // start of user buffer
|
||||||
|
U8 *curr; // next alloc point
|
||||||
|
U8 *end; // one past end of user buffer
|
||||||
|
int checkpoint_level; // level of miniarenatmp_begin stacks
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct MiniArenaCheckpoint MiniArenaCheckpoint;
|
||||||
|
struct MiniArenaCheckpoint {
|
||||||
|
U8 *alloc_point;
|
||||||
|
MiniArena *arena;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LARENA_STATIC_INITIALIZER(data) LARENA_INITIALIZER((data), sizeof(data))
|
||||||
|
#define LARENA_INITIALIZER(data, sz) {.start = (data), .curr = (data), .end = (data) + sz, .checkpoint_level = 0}
|
||||||
|
#define LARENA_DEFINE(var_name, size_, alignment_) \
|
||||||
|
struct { \
|
||||||
|
_Alignas(alignment_) U8 memory[size_]; \
|
||||||
|
} var_name##_arena_memory; \
|
||||||
|
MiniArena var_name = LARENA_STATIC_INITIALIZER(var_name##_arena_memory.memory)
|
||||||
|
#define LARENA_ALLOC_TYPE(allocator, type_) miniarenaalloc_aligned((allocator), sizeof(type_), _Alignof(type_))
|
||||||
|
#define LARENA_ALLOC_ARRAY(allocator, type_, nr_elements_) miniarenaalloc_aligned((allocator), (nr_elements_) * sizeof(type_), _Alignof(type_))
|
||||||
|
static INLINE size_t miniarena_size(const MiniArena *arena)
|
||||||
|
{
|
||||||
|
return (size_t)(arena->end - arena->start);
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE size_t miniarena_used(const MiniArena *arena)
|
||||||
|
{
|
||||||
|
return (size_t)(arena->curr - arena->start);
|
||||||
|
}
|
||||||
|
static INLINE size_t miniarena_available(const MiniArena *arena)
|
||||||
|
{
|
||||||
|
return miniarena_size(arena) - miniarena_used(arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void miniarena_init(MiniArena *arena, void *memory, size_t sz)
|
||||||
|
{
|
||||||
|
arena->start = arena->curr = (U8 *)memory;
|
||||||
|
arena->end = arena->start + sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE MiniArenaCheckpoint miniarenatmp_begin(MiniArena *arena)
|
||||||
|
{
|
||||||
|
MiniArenaCheckpoint checkpoint = {};
|
||||||
|
|
||||||
|
checkpoint.arena = arena;
|
||||||
|
checkpoint.alloc_point = arena->curr;
|
||||||
|
arena->checkpoint_level++;
|
||||||
|
|
||||||
|
return checkpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void miniarenatmp_end(MiniArenaCheckpoint *state)
|
||||||
|
{
|
||||||
|
MiniArena *arena = state->arena;
|
||||||
|
Assert(arena->checkpoint_level > 0);
|
||||||
|
arena->curr = state->alloc_point;
|
||||||
|
arena->checkpoint_level--;
|
||||||
|
}
|
||||||
|
static INLINE void *miniarena_push(MiniArena *arena, size_t sz)
|
||||||
|
{
|
||||||
|
if (sz > miniarena_available(arena)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *start = arena->curr;
|
||||||
|
arena->curr += sz;
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[gnu::alloc_align(3)]]
|
||||||
|
static INLINE void *miniaren_push_aligned(MiniArena *arena, size_t sz, unsigned int align)
|
||||||
|
{
|
||||||
|
Assert(IsPow2(align));
|
||||||
|
|
||||||
|
uintptr_t curr = (uintptr_t)arena->curr;
|
||||||
|
uintptr_t aligned = AlignUp(curr, align);
|
||||||
|
U8 *start = (U8 *)aligned;
|
||||||
|
|
||||||
|
if (sz > (size_t)(arena->end - start)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
arena->curr = start + sz;
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void miniarena_reset(MiniArena *arena)
|
||||||
|
{
|
||||||
|
arena->curr = arena->start;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user