Reimplement the arena

This commit is contained in:
kamkow1
2025-06-01 01:47:47 +02:00
parent a191abc2b7
commit 3636b08c10
2 changed files with 49 additions and 98 deletions

View File

@ -9,13 +9,13 @@ typedef struct {
int main(void)
{
Arena *arena = arena_make(sizeof(int));
defer { arena_destroy(arena); }
Arena arena = gebs_arena_get(4*1024);
defer { arena_destroy(&arena); }
Ints ints = {0};
defer { list_free_alloc(arena, &ints); }
for (size_t i = 0; i < 1000; i++) {
list_append_alloc(arena, &ints, i);
for (size_t i = 0; i < 100; i++) {
list_append_alloc(&arena, &ints, i);
gebs_arena_reset(&arena);
}
for (size_t i = 0; i < ints.count; i++) {
printf("%zu\n", i);

137
gebs.h
View File

@ -33,6 +33,7 @@
# include <sys/stat.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/mman.h>
#else
# error "Unknown GEBS_PLATFORM"
#endif
@ -96,31 +97,32 @@ void gebs_default_allocator_free(void *self, void *memory);
void *gebs_default_allocator_realloc(void *self, void *memory,
size_t prev_size, size_t new_size);
typedef struct Gebs_Arena_Allocation {
size_t index;
size_t size;
char *ptr;
struct Gebs_Arena_Allocation *next;
} Gebs_Arena_Allocation;
typedef struct {
void *(*malloc)(void *self, size_t size);
void (*free)(void *self, void *memory);
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
char *region;
size_t index;
size_t size;
void *buffer;
void *end;
size_t capacity;
} Gebs_Arena;
void gebs_arena_reset(Gebs_Arena *a);
void gebs_arena_destroy(Gebs_Arena *a);
Gebs_Arena *gebs_arena_make(size_t size);
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size);
void *gebs_arena_malloc(void *self, size_t size);
void gebs_arena_free(void *self, void *memory);
void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_size);
#define gebs_arena_get(cap) \
({ \
Gebs_Arena __arena = {0}; \
__arena.malloc = &gebs_arena_malloc; \
__arena.realloc = &gebs_arena_realloc; \
__arena.free = &gebs_arena_free; \
__arena.capacity = (cap); \
__arena; \
})
// ----------------------------------------------------------------------------
// Dynamic list
// ----------------------------------------------------------------------------
@ -301,7 +303,7 @@ void gebs_rebuild_self1_alloc(Gebs_Allocator *alloc, int argc, char ** argv,
# define GEBS_SCRATCH_ARENA_SIZE 4096
#endif
extern Gebs_Arena *gebs_scratch_arena;
extern Gebs_Arena gebs_scratch_arena;
char *gebs_fmt(const char *fmt, ...);
void gebs_scratch_arena_reset(void);
@ -316,6 +318,7 @@ int gebs_cmd_run_sync_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd)
{
Gebs_String_Builder sb = {0};
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items);
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
@ -363,6 +366,7 @@ int gebs_cmd_run_sync_collect_alloc(Gebs_Allocator *alloc, Gebs_Cmd *cmd, Gebs_S
{
Gebs_String_Builder sb = {0};
gebs_nsl_join_alloc(alloc, cmd, &sb, " ");
gebs_sb_finish_alloc(alloc, &sb);
GEBS_LOGI("cmd `%s`\n", sb.items);
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
@ -449,68 +453,23 @@ void *gebs_default_allocator_realloc(discard void *self, void *memory,
return p;
}
Gebs_Arena *gebs_arena_make(size_t size)
{
Gebs_Arena *a;
if (size == 0) {
return NULL;
}
a = malloc(sizeof(*a));
if (a == NULL) {
return NULL;
}
a->malloc = &gebs_arena_malloc;
a->free = &gebs_arena_free;
a->realloc = &gebs_arena_realloc;
a->region = malloc(size);
if (a->region == NULL) {
free(a);
return NULL;
}
a->index = 0;
a->size = size;
return a;
}
Gebs_Arena *gebs_arena_expand(Gebs_Arena *a, size_t new_size)
{
if (a == NULL || new_size <= a->size) {
return NULL;
}
a->region = realloc(a->region, new_size);
if (a->region == NULL) {
return NULL;
}
a->size = new_size;
return a;
}
void *gebs_arena_malloc(void *self, size_t size)
{
Gebs_Arena *a = (Gebs_Arena *)self;
unsigned int offset;
if (size == 0) {
return NULL;
if (a->buffer == NULL) {
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
int prot = PROT_READ | PROT_WRITE;
int vis = MAP_SHARED | MAP_ANONYMOUS;
a->buffer = mmap(0, a->capacity, prot, vis, -1, 0);
#else
# error "gebs_arena_malloc unknown platform"
#endif
a->end = a->buffer;
}
if (a == NULL || a->region == NULL) {
return NULL;
}
offset = 0;
if (a->size - (a->index + offset) < size) {
return NULL;
}
a->index += size;
return a->region + (a->index - size);
void *p = a->end;
a->end = (void *)((uintptr_t)a->end + size);
return p;
}
void gebs_arena_free(discard void *self, discard void *memory)
@ -518,53 +477,45 @@ void gebs_arena_free(discard void *self, discard void *memory)
}
void *gebs_arena_realloc(void *self, void *memory,
discard size_t prev_size, size_t new_size)
size_t prev_size, size_t new_size)
{
Gebs_Arena *a = (Gebs_Arena *)self;
uintptr_t offset = (char *)memory - a->region;
gebs_arena_expand(a, a->size + new_size);
return a->region + offset;
void *new = gebs_arena_malloc(a, new_size);
memcpy(new, memory, prev_size);
return new;
}
void gebs_arena_reset(Gebs_Arena *a)
{
if (a == NULL) {
return;
}
a->index = 0;
a->end = a->buffer;
}
void gebs_arena_destroy(Gebs_Arena *a)
{
if (a == NULL) {
return;
}
if (a->region != NULL) {
free(a->region);
}
free(a);
#if GEBS_PLATFORM == GEBS_PLATFORM_POSIX
munmap(a->buffer, a->capacity);
#else
# error "gebs_arena_destroy unknown platform"
#endif
}
// ----------------------------------------------------------------------------
// Scratch arena
// ----------------------------------------------------------------------------
Gebs_Arena *gebs_scratch_arena;
Gebs_Arena gebs_scratch_arena;
__attribute__((constructor))
void gebs_scratch_areana_init(void)
{
gebs_scratch_arena = gebs_arena_make(GEBS_SCRATCH_ARENA_SIZE);
gebs_scratch_arena = gebs_arena_get(4*1024);
}
__attribute__((destructor))
void gebs_scratch_areana_free(void)
{
gebs_arena_destroy(gebs_scratch_arena);
gebs_arena_destroy(&gebs_scratch_arena);
}
char *gebs_fmt(const char *fmt, ...)
@ -577,7 +528,7 @@ char *gebs_fmt(const char *fmt, ...)
size_t size = vsnprintf(NULL, 0, fmt, list_copy);
va_end(list_copy);
char *buf = gebs_malloc(gebs_scratch_arena, size+1);
char *buf = gebs_malloc(&gebs_scratch_arena, size+1);
vsprintf(buf, fmt, list);
va_end(list);
return buf;
@ -585,7 +536,7 @@ char *gebs_fmt(const char *fmt, ...)
void gebs_scratch_arena_reset(void)
{
gebs_arena_reset(gebs_scratch_arena);
gebs_arena_reset(&gebs_scratch_arena);
}
// ----------------------------------------------------------------------------