colla/arena.h
alessandro bason a66e58193f .
2025-06-24 17:47:08 +02:00

108 lines
2.7 KiB
C

#ifndef COLLA_ARENA_H
#define COLLA_ARENA_H
#include "core.h"
#if COLLA_DEBUG
#include "str.h"
#endif
#if COLLA_WIN && !COLLA_TCC
#define alignof __alignof
#endif
typedef enum arena_type_e {
ARENA_TYPE_NONE, // only here so that a 0 initialised arena is valid
ARENA_VIRTUAL,
ARENA_MALLOC,
ARENA_MALLOC_ALWAYS,
ARENA_STATIC,
} arena_type_e;
typedef enum alloc_flags_e {
ALLOC_FLAGS_NONE = 0,
ALLOC_NOZERO = 1 << 0,
ALLOC_SOFT_FAIL = 1 << 1,
} alloc_flags_e;
#if COLLA_DEBUG
typedef struct alloc_header_t alloc_header_t;
struct alloc_header_t {
char type_name[16];
u32 size;
u32 count;
alloc_header_t *next;
};
void arena__print_crash(arena_t *arena);
#endif
typedef struct arena_t arena_t;
struct arena_t {
u8 *beg;
u8 *cur;
u8 *end;
arena_type_e type;
#if COLLA_DEBUG
strview_t file;
int line;
alloc_header_t *head;
#endif
};
typedef struct arena_desc_t arena_desc_t;
struct arena_desc_t {
#if COLLA_DEBUG
strview_t file;
int line;
#endif
arena_type_e type;
usize size;
u8 *static_buffer;
};
typedef struct arena_alloc_desc_t arena_alloc_desc_t;
struct arena_alloc_desc_t {
#if COLLA_DEBUG
strview_t type_name;
#endif
arena_t *arena;
usize count;
alloc_flags_e flags;
usize align;
usize size;
};
// arena_type_e type, usize allocation, [ byte *static_buffer ]
#if !COLLA_DEBUG
#define arena_make(...) arena_init(&(arena_desc_t){ __VA_ARGS__ })
#else
#define arena_make(...) arena_init(&(arena_desc_t){ strv(__FILE__), __LINE__, __VA_ARGS__ })
#endif
// arena_t *arena, T type, [ usize count, alloc_flags_e flags, usize align, usize size ]
#if !COLLA_DEBUG
#define alloc(arenaptr, type, ...) arena_alloc(&(arena_alloc_desc_t){ .size = sizeof(type), .count = 1, .align = alignof(type), .arena = arenaptr, __VA_ARGS__ })
#else
#define alloc(arenaptr, type, ...) arena_alloc(&(arena_alloc_desc_t){ .type_name = strv(#type), .size = sizeof(type), .count = 1, .align = alignof(type), .arena = arenaptr, __VA_ARGS__ })
#endif
// simple arena that always calls malloc internally, this is useful if you need
// malloc for some reason but want to still use the arena interface
// WARN: most arena functions outside of alloc/scratch won't work!
// you also need to each allocation afterwards! this is still
// malloc
extern arena_t malloc_arena;
arena_t arena_init(const arena_desc_t *desc);
void arena_cleanup(arena_t *arena);
arena_t arena_scratch(arena_t *arena, usize size);
void *arena_alloc(const arena_alloc_desc_t *desc);
usize arena_tell(arena_t *arena);
usize arena_remaining(arena_t *arena);
usize arena_capacity(arena_t *arena);
void arena_rewind(arena_t *arena, usize from_start);
void arena_pop(arena_t *arena, usize amount);
#endif