This commit is contained in:
2026-07-07 06:40:47 +02:00
parent 66306ad8e4
commit 57329340e2

44
arena.h
View File

@@ -1,4 +1,4 @@
// arena.h - v1.2.1 - MIT License // arena.h - v1.2.2 - MIT License
// single header library for region-based memory management. // single header library for region-based memory management.
// //
// [License and changelog] // [License and changelog]
@@ -21,18 +21,19 @@
// Note: every compile-time option listed here should be configured before // Note: every compile-time option listed here should be configured before
// the #include "arena.h" // the #include "arena.h"
// //
// #define ARENA_REGION_CAPACITY new_region_capacity_in_bytes (4096) // #define ARENA_REGION_CAPACITY new_region_capacity_in_bytes (8*1024)
// //
// This macro defines the default capacity for arena regions. // This macro defines the default capacity for arena regions.
// //
// #define ARENA_REGION_GROWTH_FACTOR new_region_growth_factor (1.5f) // #define ARENA_REGION_GROWTH_FACTOR new_region_growth_factor (2)
// //
// This macro defines the growth factor of the capacity for every // This macro defines the growth factor of the capacity for every
// subsequent region in all arenas. // subsequent region in all arenas.
// //
// #define ARENA_ALIGNMENT alignment (8) // #define ARENA_ALIGNMENT alignment (alignof(max_align_t))
// //
// This macro defines the memory alignment used for allocations. // This macro defines the memory alignment used for allocations.
// Must be a power of two.
// //
// #define ARENA_NO_ASSERT // #define ARENA_NO_ASSERT
// //
@@ -159,7 +160,7 @@ int main(void)
#endif // ARENA_REGION_CAPACITY #endif // ARENA_REGION_CAPACITY
#ifndef ARENA_REGION_GROWTH_FACTOR #ifndef ARENA_REGION_GROWTH_FACTOR
# define ARENA_REGION_GROWTH_FACTOR 1.5f # define ARENA_REGION_GROWTH_FACTOR 2
#endif // ARENA_REGION_GROWTH_FACTOR #endif // ARENA_REGION_GROWTH_FACTOR
#ifndef ARENA_ALIGNMENT #ifndef ARENA_ALIGNMENT
@@ -300,23 +301,29 @@ void *arena_alloc(Arena *a, size_t size)
return NULL; return NULL;
} }
// Ensure memory alignment of requested size
size = arena__align(size);
// Check for overflow // Check for overflow
if (size > SIZE_MAX - sizeof(Arena_Region)) { if (size > SIZE_MAX - sizeof(Arena_Region)) {
ARENA_ASSERT(false && "Requested size too large"); ARENA_ASSERT(false && "Requested size too large");
return NULL; return NULL;
} }
// Ensure memory alignment of requested size
size = arena__align(size);
// Get the next region capacity multiplied by the growth factor // Get the next region capacity multiplied by the growth factor
size_t region_capacity = (a->region_capacity == 0 size_t region_capacity = (a->region_capacity == 0
? ARENA_REGION_CAPACITY : a->region_capacity); ? ARENA_REGION_CAPACITY : a->region_capacity);
if (a->tail != NULL) { if (a->tail != NULL) {
region_capacity = a->tail->capacity * ARENA_REGION_GROWTH_FACTOR; size_t max_cap = (SIZE_MAX / 2) - sizeof(Arena_Region);
// Edge case for small growth factors
if (region_capacity <= a->tail->capacity) { if (a->tail->capacity >= max_cap / (ARENA_REGION_GROWTH_FACTOR)) {
region_capacity = a->tail->capacity + 1; region_capacity = max_cap;
} else {
region_capacity = a->tail->capacity * (ARENA_REGION_GROWTH_FACTOR);
// Edge case for small growth factors
if (region_capacity <= a->tail->capacity) {
region_capacity = a->tail->capacity + (4 * 1024);
}
} }
} }
@@ -344,7 +351,9 @@ void *arena_alloc(Arena *a, size_t size)
// Find first suitable region // Find first suitable region
Arena_Region *r = a->tail; Arena_Region *r = a->tail;
Arena_Region *last = r;
while (r != NULL && size > r->capacity - r->count) { while (r != NULL && size > r->capacity - r->count) {
last = r;
r = r->next; r = r->next;
} }
@@ -354,18 +363,19 @@ void *arena_alloc(Arena *a, size_t size)
ARENA_ASSERT(false && "Region count overflow"); ARENA_ASSERT(false && "Region count overflow");
return NULL; return NULL;
} }
a->tail = r;
r->count += size; r->count += size;
return r->data + r->count - size; return r->data + r->count - size;
} }
// If not found append a new region // If not found append a new region
a->tail->next = (Arena_Region*)ARENA_MALLOC(sizeof(*a->tail) + alloc_size); last->next = (Arena_Region*)ARENA_MALLOC(sizeof(*a->tail) + alloc_size);
if (a->tail->next == NULL) { if (last->next == NULL) {
ARENA_ASSERT(false && "Allocation failed"); ARENA_ASSERT(false && "Allocation failed");
return NULL; return NULL;
} }
a->tail = a->tail->next; a->tail = last->next;
a->tail->next = NULL; a->tail->next = NULL;
a->tail->count = size; a->tail->count = size;
a->tail->capacity = alloc_size; a->tail->capacity = alloc_size;
@@ -434,7 +444,7 @@ char *arena_sprintf(Arena *a, const char *fmt, ...)
size_t needed = (size_t)n + 1; size_t needed = (size_t)n + 1;
// If it fits commit and return // If it fits commit and return
if (needed <= available) { if (arena__align(needed) <= available) {
r->count += arena__align(needed); r->count += arena__align(needed);
va_end(args); va_end(args);
return result; return result;
@@ -508,6 +518,8 @@ size_t arena__align(size_t n)
/* /*
* Revision history: * Revision history:
* *
* 1.2.2 (2026-07-07) Fix various memory problems;
* make ARENA_REGION_GROWTH_FACTOR an integer
* 1.2.1 (2026-04-08) Region growth factor handling with new * 1.2.1 (2026-04-08) Region growth factor handling with new
* ARENA_REGION_GROWTH_FACTOR macro * ARENA_REGION_GROWTH_FACTOR macro
* 1.2.0 (2026-04-08) New functions: arena_sprintf(), arena_snapshot(), * 1.2.0 (2026-04-08) New functions: arena_sprintf(), arena_snapshot(),