Add an arena out-of-memory handler

This commit is contained in:
kamkow1
2025-06-01 12:47:40 +02:00
parent 5a1fe0521f
commit dd74b7f78a
2 changed files with 26 additions and 2 deletions

View File

@ -9,7 +9,8 @@ typedef struct {
int main(void)
{
Arena arena = gebs_arena_get(4*1024);
/* Arena arena = gebs_arena_get(512); */
Arena arena = gebs_arena_get(128);
defer { arena_destroy(&arena); }
Ints ints = {0};

25
gebs.h
View File

@ -169,7 +169,7 @@ 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 {
typedef struct Gebs_Arena {
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);
@ -177,6 +177,8 @@ typedef struct {
void *buffer;
void *end;
size_t capacity;
void (*out_of_memory_handler)(struct Gebs_Arena *self, size_t requested);
} Gebs_Arena;
void gebs_arena_reset(Gebs_Arena *a);
@ -184,6 +186,7 @@ void gebs_arena_destroy(Gebs_Arena *a);
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);
void gebs_arena_out_of_memory_handler(Gebs_Arena *self, size_t requested);
#define gebs_arena_get(cap) \
({ \
@ -192,6 +195,7 @@ void *gebs_arena_realloc(void *self, void *memory, size_t prev_size, size_t new_
__arena.realloc = &gebs_arena_realloc; \
__arena.free = &gebs_arena_free; \
__arena.capacity = (cap); \
__arena.out_of_memory_handler = &gebs_arena_out_of_memory_handler; \
__arena; \
})
@ -541,6 +545,15 @@ void *gebs_arena_malloc(void *self, size_t size)
}
void *p = a->end;
a->end = (void *)((uintptr_t)a->end + size);
size_t requested = (uintptr_t)a->end - (uintptr_t)a->buffer;
if (requested > a->capacity) {
if (a->out_of_memory_handler == NULL) {
abort();
}
a->out_of_memory_handler(a, requested);
}
return p;
}
@ -572,6 +585,16 @@ void gebs_arena_destroy(Gebs_Arena *a)
#endif
}
void gebs_arena_out_of_memory_handler(Gebs_Arena *self, size_t requested)
{
GEBS_LOGE("Arena ran out of memory. capacity = %zu, requested %zu\n",
self->capacity, requested);
GEBS_LOGI("Arena: buffer %p, end %p, diff %zu\n",
self->buffer, self->end,
(size_t)((uintptr_t)self->end - (uintptr_t)self->buffer));
abort();
}
// ----------------------------------------------------------------------------
// Scratch arena
// ----------------------------------------------------------------------------