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) 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); } defer { arena_destroy(&arena); }
Ints ints = {0}; 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, void *gebs_default_allocator_realloc(void *self, void *memory,
size_t prev_size, size_t new_size); size_t prev_size, size_t new_size);
typedef struct { typedef struct Gebs_Arena {
void *(*malloc)(void *self, size_t size); void *(*malloc)(void *self, size_t size);
void (*free)(void *self, void *memory); void (*free)(void *self, void *memory);
void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size); void *(*realloc)(void *self, void *memory, size_t prev_size, size_t new_size);
@ -177,6 +177,8 @@ typedef struct {
void *buffer; void *buffer;
void *end; void *end;
size_t capacity; size_t capacity;
void (*out_of_memory_handler)(struct Gebs_Arena *self, size_t requested);
} Gebs_Arena; } Gebs_Arena;
void gebs_arena_reset(Gebs_Arena *a); 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_malloc(void *self, size_t size);
void gebs_arena_free(void *self, void *memory); 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_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) \ #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.realloc = &gebs_arena_realloc; \
__arena.free = &gebs_arena_free; \ __arena.free = &gebs_arena_free; \
__arena.capacity = (cap); \ __arena.capacity = (cap); \
__arena.out_of_memory_handler = &gebs_arena_out_of_memory_handler; \
__arena; \ __arena; \
}) })
@ -541,6 +545,15 @@ void *gebs_arena_malloc(void *self, size_t size)
} }
void *p = a->end; void *p = a->end;
a->end = (void *)((uintptr_t)a->end + size); 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; return p;
} }
@ -572,6 +585,16 @@ void gebs_arena_destroy(Gebs_Arena *a)
#endif #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 // Scratch arena
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------