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

40
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.
//
// [License and changelog]
@@ -21,18 +21,19 @@
// Note: every compile-time option listed here should be configured before
// 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.
//
// #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
// 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.
// Must be a power of two.
//
// #define ARENA_NO_ASSERT
//
@@ -159,7 +160,7 @@ int main(void)
#endif // ARENA_REGION_CAPACITY
#ifndef ARENA_REGION_GROWTH_FACTOR
# define ARENA_REGION_GROWTH_FACTOR 1.5f
# define ARENA_REGION_GROWTH_FACTOR 2
#endif // ARENA_REGION_GROWTH_FACTOR
#ifndef ARENA_ALIGNMENT
@@ -300,23 +301,29 @@ void *arena_alloc(Arena *a, size_t size)
return NULL;
}
// Ensure memory alignment of requested size
size = arena__align(size);
// Check for overflow
if (size > SIZE_MAX - sizeof(Arena_Region)) {
ARENA_ASSERT(false && "Requested size too large");
return NULL;
}
// Ensure memory alignment of requested size
size = arena__align(size);
// Get the next region capacity multiplied by the growth factor
size_t region_capacity = (a->region_capacity == 0
? ARENA_REGION_CAPACITY : a->region_capacity);
if (a->tail != NULL) {
region_capacity = a->tail->capacity * ARENA_REGION_GROWTH_FACTOR;
size_t max_cap = (SIZE_MAX / 2) - sizeof(Arena_Region);
if (a->tail->capacity >= max_cap / (ARENA_REGION_GROWTH_FACTOR)) {
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 + 1;
region_capacity = a->tail->capacity + (4 * 1024);
}
}
}
@@ -344,7 +351,9 @@ void *arena_alloc(Arena *a, size_t size)
// Find first suitable region
Arena_Region *r = a->tail;
Arena_Region *last = r;
while (r != NULL && size > r->capacity - r->count) {
last = r;
r = r->next;
}
@@ -354,18 +363,19 @@ void *arena_alloc(Arena *a, size_t size)
ARENA_ASSERT(false && "Region count overflow");
return NULL;
}
a->tail = r;
r->count += size;
return r->data + r->count - size;
}
// If not found append a new region
a->tail->next = (Arena_Region*)ARENA_MALLOC(sizeof(*a->tail) + alloc_size);
if (a->tail->next == NULL) {
last->next = (Arena_Region*)ARENA_MALLOC(sizeof(*a->tail) + alloc_size);
if (last->next == NULL) {
ARENA_ASSERT(false && "Allocation failed");
return NULL;
}
a->tail = a->tail->next;
a->tail = last->next;
a->tail->next = NULL;
a->tail->count = 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;
// If it fits commit and return
if (needed <= available) {
if (arena__align(needed) <= available) {
r->count += arena__align(needed);
va_end(args);
return result;
@@ -508,6 +518,8 @@ size_t arena__align(size_t n)
/*
* 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
* ARENA_REGION_GROWTH_FACTOR macro
* 1.2.0 (2026-04-08) New functions: arena_sprintf(), arena_snapshot(),