cbase 1.50.0
C/C++ Static Template
Loading...
Searching...
No Matches
mem_arena.c
Go to the documentation of this file.
1
7
8#include "memory/mem_arena.h"
9#include "memory/mem_allocator.h" // Needed for the Allocator bridge
10#include "memory/mem_os.h"
11#include <string.h>
12
13#define MEM_ARENA_COMMIT_SIZE KB(64)
14
15static void *
16mem_arena_push_internal(MemArena *arena, usize size, usize alignment)
17{
18 ASSERT(IS_POW2(alignment) && "alignment must be a non-zero power of 2");
19
20 usize current_pos = ALIGN_UP_POW2(arena->pos, alignment);
21
22 if (size > arena->reserve - current_pos) {
23 ASSERT(0 && "Arena OOM: allocation exceeds reserved capacity");
24 return NULL;
25 }
26
27 usize next_pos = current_pos + size;
28
29 if (next_pos > arena->commit) {
30 usize needed = next_pos - arena->commit;
31 usize cmt_size = ALIGN_UP_POW2(needed, MEM_ARENA_COMMIT_SIZE);
32 usize cmt_clamped = MIN(cmt_size, arena->reserve - arena->commit);
33
34 b32 ok = mem_os_commit(arena->base + arena->commit, cmt_clamped);
35 if (!ok) {
36 ASSERT(0 && "Arena OOM: OS refused to commit physical RAM");
37 return NULL;
38 }
39 arena->commit += cmt_clamped;
40 }
41
42 void *result = arena->base + current_pos;
43 arena->pos = next_pos;
44 return result;
45}
46
49{
50 MemArena arena = {0};
51 arena.base = (u8 *)mem_os_reserve(reserve_size);
52 if (arena.base != NULL) {
53 arena.reserve = reserve_size;
54 }
55 return arena;
56}
57
58void
60{
61 if (arena->base != NULL) {
62 mem_os_release(arena->base, arena->reserve);
63 arena->base = NULL;
64 arena->reserve = 0;
65 arena->pos = 0;
66 arena->commit = 0;
67 }
68}
69
70void *
72{
73 return mem_arena_push_internal(arena, size, MEM_ARENA_ALIGNMENT);
74}
75
76void *
78{
79 void *result = mem_arena_push_internal(arena, size, MEM_ARENA_ALIGNMENT);
80 if (result != NULL) {
81 MEM_ZERO(result, size);
82 }
83 return result;
84}
85
86void *
88{
89 void *result = mem_arena_push_internal(arena, size, alignment);
90 if (result != NULL) {
91 MEM_ZERO(result, size);
92 }
93 return result;
94}
95
96void
98{
99 ASSERT(pos <= arena->pos && "mem_arena_pop_to: pos is ahead of current position");
100 usize clamped = MIN(pos, arena->pos);
101 arena->pos = clamped;
102}
103
104void
106{
107 mem_arena_pop_to(arena, 0);
108}
109
110void
112{
113 if (arena->commit > 0) {
114 mem_os_decommit(arena->base, arena->commit);
115 arena->commit = 0;
116 }
117 arena->pos = 0;
118}
119
120char *
121mem_arena_push_cstr(MemArena *arena, const char *str, usize len)
122{
123 char *buf = (char *)mem_arena_push_zero(arena, len + 1);
124 if (buf != NULL) {
125 MEM_COPY(buf, str, len);
126 buf[len] = '\0';
127 }
128 return buf;
129}
130
133{
134 MemArenaTemp temp;
135 temp.arena = arena;
136 temp.pos = arena->pos;
137 return temp;
138}
139
140void
145
147
148static void *
149mem_arena_alloc_impl(MemAllocMode mode, void *ctx, usize size, void *old_ptr)
150{
151 MemArena *arena = (MemArena *)ctx;
152 (void)old_ptr; // Arenas don't use the old pointer for frees/reallocs
153
154 switch (mode) {
156 return mem_arena_push_zero(arena, size);
158 // Arenas do not free individual allocations!
159 return NULL;
161 // Reallocating in an arena just means pushing a brand new block.
162 // (The mem_realloc wrapper in mem_allocator.h handles copying the old data).
163 return mem_arena_push_zero(arena, size);
165 mem_arena_clear(arena);
166 return NULL;
167 }
168 return NULL;
169}
170
173{
174 MemAllocator alloc;
175 alloc.fn = mem_arena_alloc_impl;
176 alloc.ctx = arena;
177 return alloc;
178}
#define ALIGN_UP_POW2(x, p)
Aligns a value UP to the nearest multiple of p (must be power of 2).
#define IS_POW2(x)
Checks if a given integer is a strictly positive power of 2.
uint8_t u8
Definition base_types.h:46
#define ASSERT(expr)
Standard runtime assertion. Triggers a debug break on failure.
MemAllocMode
Describes the type of memory operation being requested.
@ MEM_ALLOC_MODE_FREE_ALL
@ MEM_ALLOC_MODE_ALLOC
@ MEM_ALLOC_MODE_REALLOC
@ MEM_ALLOC_MODE_FREE
void mem_arena_clear(MemArena *arena)
Resets the arena pointer to zero, freeing all allocations in O(1).
Definition mem_arena.c:105
void mem_arena_temp_end(MemArenaTemp temp)
Restores the arena to the position saved in temp.
Definition mem_arena.c:141
void mem_arena_release(MemArena *arena)
Returns all virtual memory back to the operating system.
Definition mem_arena.c:59
#define MEM_ARENA_ALIGNMENT
The default byte alignment for memory pushed onto the arena.
Definition mem_arena.h:67
void * mem_arena_push_zero(MemArena *arena, usize size)
Allocates bytes and explicitly zero-initializes them.
Definition mem_arena.c:77
void mem_arena_clear_and_decommit(MemArena *arena)
Clears the arena and returns all committed physical RAM to the OS.
Definition mem_arena.c:111
void * mem_arena_push_aligned(MemArena *arena, usize size, usize alignment)
Allocates bytes with a specific custom alignment.
Definition mem_arena.c:87
void * mem_arena_push(MemArena *arena, usize size)
Allocates bytes sequentially on the arena without zeroing.
Definition mem_arena.c:71
void mem_arena_pop_to(MemArena *arena, usize pos)
Rewinds the arena's pointer to a specific offset.
Definition mem_arena.c:97
MemAllocator mem_arena_allocator(MemArena *arena)
Wraps a MemArena in the generic MemAllocator interface.
Definition mem_arena.c:172
char * mem_arena_push_cstr(MemArena *arena, const char *str, usize len)
Copies a C string into the arena and appends a NUL terminator.
Definition mem_arena.c:121
MemArenaTemp mem_arena_temp_begin(MemArena *arena)
Temporary Memory API.
Definition mem_arena.c:132
MemArena mem_arena_create(usize reserve_size)
Initializes a new virtual memory Arena.
Definition mem_arena.c:48
void mem_os_release(void *ptr, usize size)
Releases a reserved virtual address block entirely back to the OS.
Definition mem_os.c:50
b32 mem_os_commit(void *ptr, usize size)
Commits physical RAM to a previously reserved virtual address block.
Definition mem_os.c:29
void * mem_os_reserve(usize size)
Reserves a contiguous block of virtual address space.
Definition mem_os.c:18
void mem_os_decommit(void *ptr, usize size)
Decommits physical RAM, returning it to the OS.
Definition mem_os.c:39
#define MEM_COPY(dst, src, size)
Copies memory using memmove (overlap-safe).
#define MEM_ZERO(ptr, size)
Zeroes a block of memory. Wraps memset.
size_t usize
Definition base_types.h:68
#define MIN(a, b)
Returns the minimum of two values (Standard C fallback).
int32_t b32
Definition base_types.h:111
Generic interface for abstracting memory allocators.
static void * mem_arena_alloc_impl(MemAllocMode mode, void *ctx, usize size, void *old_ptr)
Generic Allocator Interface Implementation.
Definition mem_arena.c:149
High-performance virtual memory Arena Allocator.
Cross-platform wrappers for OS-level virtual memory management.
An abstract allocator interface.
MemAllocFn fn
A virtual memory-backed linear allocator.
Definition mem_arena.h:70
usize reserve
Definition mem_arena.h:74
usize commit
Definition mem_arena.h:73
u8 * base
Definition mem_arena.h:71
usize pos
Definition mem_arena.h:72
A temporary snapshot of an arena's state.
Definition mem_arena.h:78
MemArena * arena
Definition mem_arena.h:79