From 9657cfdb43ef7f8f014f23d9b0f7dfe31803feba Mon Sep 17 00:00:00 2001 From: seajee Date: Sat, 6 Sep 2025 02:22:52 +0200 Subject: [PATCH] v1.0.2 release --- arena.h | 69 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/arena.h b/arena.h index 9f1dc6f..e9cf126 100644 --- a/arena.h +++ b/arena.h @@ -1,15 +1,33 @@ -// arena.h - v1.0.1 - MIT License - https://github.com/seajee/arena.h +// arena.h - v1.0.2 - MIT License - https://github.com/seajee/arena.h // single header library for region-based memory management. // -// License and changelog: +// [License and changelog] // // See end of file. // -// Compile-time options: +// [Single header library usage] +// +// Including this header file as such does what you normally expect. +// +// If you also need to include all of the function implementations you +// need to #define ARENA_IMPLEMENTATION before including the header file +// like this: +// +// #define ARENA_IMPLEMENTATION +// #include "arena.h" +// +// [Compile-time options] // // Note: every compile-time option listed here should be configured before // the #include "arena.h" // +// #define ARENA_NO_ASSERT +// +// This macro disables assertions that happen when a reallocation +// fails. The disabled assertions will be replaced with a simple +// condition that returns NULL when it fails. Note that ARENA_ASSERT +// is only used in arena_alloc(). +// // #define ARENA_REGION_CAPACITY new_region_capacity_in_bytes (4096) // // This macro defines the default capacity for arena regions. @@ -17,7 +35,8 @@ // #define ARENA_ASSERT my_assert // // This macro defines an alternative function for assertions. In this -// library, ARENA_ASSERT is only used when ARENA_REALLOC fails. +// library, ARENA_ASSERT is only used when arena_alloc() fails. Will +// be overwritten if ARENA_NO_ASSERT is defined. // // #define ARENA_REALLOC my_realloc // #define ARENA_FREE my_free @@ -26,7 +45,7 @@ // and deallocation on the heap. They are only used for managing // Arena_Region structures. // -// Function documentation: +// [Function documentation] // // In this library, arenas are implemented as linked lists of regions. Each // region will contain the allocated buffers. The following are all of the @@ -39,8 +58,7 @@ // configured by redefining it before including the header file. This function // is not strictly necessary for initializing an arena (see example). // -// void *arena_alloc(Arena *a, -// size_t bytes) +// void *arena_alloc(Arena *a, size_t bytes) // // This function allocates a buffer of size into the specified arena // and returns it's pointer. @@ -59,8 +77,9 @@ // Warning: this functions may cause fragmentation, consider setting an // appropriate region capacity. // -// Example: -/* +// [Example] +// +#if 0 #define ARENA_IMPLEMENTATION #include "arena.h" @@ -75,7 +94,7 @@ int main(void) arena_free(&a); // The arena can still be reused return 0; } -*/ +#endif // [Example] #ifndef ARENA_H_ #define ARENA_H_ @@ -87,10 +106,14 @@ int main(void) # define ARENA_REGION_CAPACITY (8*1024) #endif // ARENA_REGION_CAPACITY -#ifndef ARENA_ASSERT -# include -# define ARENA_ASSERT assert -#endif // ARENA_ASSERT +#ifndef ARENA_NO_ASSERT +# ifndef ARENA_ASSERT +# include +# define ARENA_ASSERT assert +# endif // ARENA_ASSERT +#else +# define ARENA_ASSERT(...) ((void)0) +#endif // ARENA_NO_ASSERT #ifndef ARENA_REALLOC # include @@ -147,7 +170,8 @@ Arena arena_create(size_t region_capacity) void *arena_alloc(Arena *a, size_t bytes) { - if (a == NULL) { + if (a == NULL || bytes == 0) { + ARENA_ASSERT(!"Invalid, parameters"); return NULL; } @@ -158,10 +182,13 @@ void *arena_alloc(Arena *a, size_t bytes) if (a->head == NULL) { size_t size = (bytes > region_capacity ? bytes : region_capacity); a->head = (Arena_Region*)ARENA_REALLOC(NULL, sizeof(*a->head) + size); - ARENA_ASSERT(a->head != NULL); + if (a->head == NULL) { + ARENA_ASSERT(!"Reallocation failed"); return NULL; } + + a->head->next = NULL; a->head->count = bytes; a->head->capacity = size; a->tail = a->head; @@ -179,11 +206,14 @@ void *arena_alloc(Arena *a, size_t bytes) if (bytes > a->tail->capacity - a->tail->count) { size_t size = (bytes > region_capacity ? bytes : region_capacity); a->tail->next = (Arena_Region*)ARENA_REALLOC(NULL, sizeof(*a->tail) + size); - ARENA_ASSERT(a->head != NULL); + if (a->tail->next == NULL) { + ARENA_ASSERT(!"Reallocation failed"); return NULL; } + a->tail = a->tail->next; + a->tail->next = NULL; a->tail->count = bytes; a->tail->capacity = size; return a->tail->data; @@ -191,7 +221,7 @@ void *arena_alloc(Arena *a, size_t bytes) } a->tail->count += bytes; - return a->tail->data + a->tail->count; + return a->tail->data + a->tail->count - bytes; } void arena_free(Arena *a) @@ -203,7 +233,7 @@ void arena_free(Arena *a) Arena_Region *cur = a->head; while (cur != NULL) { Arena_Region *next = cur->next; - free(cur); + ARENA_FREE(cur); cur = next; } @@ -234,6 +264,7 @@ void arena_reset(Arena *a) /* * Revision history: * + * 1.0.2 (2025-09-06) Bug fixes; new ARENA_NO_ASSERT macro * 1.0.1 (2025-08-02) Prevent name mangling of functions; don't reset * region_capacity in arena_free() * 1.0.0 (2025-07-24) Initial release