SBgl 0.1.0
A graphics framework in C99
Loading...
Searching...
No Matches
sbl_arena.h
Go to the documentation of this file.
1
5#ifndef SBL_ARENA_H
6#define SBL_ARENA_H
7
8#include <stddef.h>
9#include <stdint.h>
10#include <stdbool.h>
11#include <string.h> // not being used directly
12
13#ifndef SBL_ARENA_DEF
14#define SBL_ARENA_DEF
15#endif
16
17// --- Macros ---
18
19#define SBL_ARENA_PUSH_STRUCT(arena, type) ((type*)sbl_arena_alloc((arena), sizeof(type)))
20#define SBL_ARENA_PUSH_STRUCT_ZERO(arena, type) ((type*)sbl_arena_alloc_zero((arena), sizeof(type)))
21#define SBL_ARENA_PUSH_ARRAY(arena, type, count) \
22 ((type*)sbl_arena_alloc((arena), sizeof(type) * (count)))
23#define SBL_ARENA_PUSH_ARRAY_ZERO(arena, type, count) \
24 ((type*)sbl_arena_alloc_zero((arena), sizeof(type) * (count)))
25
26#define SBL_ARENA_PUSH_STRING(arena, str) \
27 ((char*)SBL_ARENA_MEMCPY(sbl_arena_alloc((arena), strlen(str) + 1), (str), strlen(str) + 1))
28
29// --- Types ---
30
34typedef struct SblArenaBlock {
35 uint64_t size;
36 uint64_t offset;
38 uint64_t _padding;
40
51
57typedef struct {
59 uint64_t offset;
61
62// Thread-local arena (extern in header unless static)
63#ifndef SBL_ARENA_STATIC
64#if __STDC_VERSION__ >= 201112L
65extern _Thread_local SblArena sbl_thread_arena;
66extern _Thread_local int sbl_thread_arena_initialized;
67#else
68extern __thread SblArena sbl_thread_arena;
69extern __thread int sbl_thread_arena_initialized;
70#endif
71#endif
72
73// --- Core API ---
74
75SBL_ARENA_DEF bool sbl_arena_init(SblArena* arena, uint64_t initial_size);
77SBL_ARENA_DEF void* sbl_arena_alloc(SblArena* arena, uint64_t size);
78SBL_ARENA_DEF void* sbl_arena_alloc_zero(SblArena* arena, uint64_t size);
80
83
85
86// Allow to override memset/memcpy
87#ifndef SBL_ARENA_MEMSET
88#include <string.h>
89#define SBL_ARENA_MEMSET(dst, val, sz) memset(dst, val, sz)
90#endif
91
92#ifndef SBL_ARENA_MEMCPY
93#include <string.h>
94#define SBL_ARENA_MEMCPY(dst, src, sz) memcpy(dst, src, sz)
95#endif
96
97#endif // SBL_ARENA_H
98
99#ifdef SBL_ARENA_IMPLEMENTATION
100#ifndef SBL_ARENA_IMPLEMENTATION_GUARD
101#define SBL_ARENA_IMPLEMENTATION_GUARD
102
103#include <stdlib.h>
104#include <stdbool.h>
105
106static uintptr_t sbl_arena__align_forward(uintptr_t ptr, uint64_t align) {
107 uintptr_t p = ptr;
108 uintptr_t a = (uintptr_t)align;
109 uintptr_t mod = p & (a - 1);
110 if (mod > 0) {
111 p += (a - mod);
112 }
113 return p;
114}
115
116static SblArenaBlock* sbl_arena__block_create(uint64_t size) {
117 uint64_t total_size = size + sizeof(SblArenaBlock);
118 SblArenaBlock* block = (SblArenaBlock*)malloc(total_size);
119 if (!block)
120 return NULL;
121 block->size = size;
122 block->offset = 0;
123 block->next = NULL;
124 return block;
125}
126
127bool sbl_arena_init(SblArena* arena, uint64_t initial_size) {
128 arena->head = sbl_arena__block_create(initial_size);
129 arena->current = arena->head;
130 return arena->head != NULL;
131}
132
133void sbl_arena_free(SblArena* arena) {
134 if (!arena)
135 return;
136 SblArenaBlock* b = arena->head;
137 while (b) {
138 SblArenaBlock* next = b->next;
139 free(b);
140 b = next;
141 }
142}
143
144void* sbl_arena_alloc(SblArena* arena, uint64_t size) {
145 if (!arena || !arena->current) return NULL;
146 uint64_t align = 16;
147 SblArenaBlock* b = arena->current;
148
149 uintptr_t curr_ptr = (uintptr_t)b + sizeof(SblArenaBlock) + b->offset;
150 uintptr_t aligned_ptr = sbl_arena__align_forward(curr_ptr, align);
151 uint64_t aligned_offset = aligned_ptr - ((uintptr_t)b + sizeof(SblArenaBlock));
152
153 if (aligned_offset + size > b->size) {
154 if (b->next && b->next->size >= size) {
155 // Reuse existing next block
156 b = b->next;
157 arena->current = b;
158 aligned_ptr = sbl_arena__align_forward((uintptr_t)b + sizeof(SblArenaBlock), align);
159 } else {
160 // Create new block, replacing any existing chain to prevent leaks
161 if (b->next) {
162 SblArenaBlock* next_to_free = b->next;
163 while (next_to_free) {
164 SblArenaBlock* n = next_to_free->next;
165 free(next_to_free);
166 next_to_free = n;
167 }
168 }
169 uint64_t next_size = b->size * 2;
170 if (size > next_size)
171 next_size = size * 2;
172 SblArenaBlock* next = sbl_arena__block_create(next_size);
173 if (!next) return NULL;
174 b->next = next;
175 arena->current = next;
176 b = next;
177 aligned_ptr = sbl_arena__align_forward((uintptr_t)b + sizeof(SblArenaBlock), align);
178 }
179 }
180
181 void* ptr = (void*)aligned_ptr;
182 b->offset = (aligned_ptr + size) - ((uintptr_t)b + sizeof(SblArenaBlock));
183 return ptr;
184}
185
186void* sbl_arena_alloc_zero(SblArena* arena, uint64_t size) {
187 void* ptr = sbl_arena_alloc(arena, size);
188 if (ptr)
189 SBL_ARENA_MEMSET(ptr, 0, size);
190 return ptr;
191}
192
193void sbl_arena_reset(SblArena* arena) {
194 SblArenaBlock* b = arena->head;
195 while (b) {
196 b->offset = 0;
197 b = b->next;
198 }
199 arena->current = arena->head;
200}
201
203 SblArenaMark mark;
204 mark.block = arena->current;
205 mark.offset = arena->current->offset;
206 return mark;
207}
208
209void sbl_arena_rewind(SblArena* arena, SblArenaMark mark) {
210 arena->current = mark.block;
211 arena->current->offset = mark.offset;
212}
213
214#ifndef SBL_ARENA_STATIC
215#if __STDC_VERSION__ >= 201112L
216_Thread_local SblArena sbl_thread_arena;
217_Thread_local int sbl_thread_arena_initialized = 0;
218#else
220__thread int sbl_thread_arena_initialized = 0;
221#endif
222
225 sbl_arena_init(&sbl_thread_arena, 1024 * 1024);
227 }
228 return &sbl_thread_arena;
229}
230#endif // SBL_ARENA_STATIC
231#endif // SBL_ARENA_IMPLEMENTATION_GUARD
232#endif // SBL_ARENA_IMPLEMENTATION
struct SblArena SblArena
Arena allocator.
__thread int sbl_thread_arena_initialized
struct SblArenaBlock SblArenaBlock
A single block of memory in the arena.
SBL_ARENA_DEF SblArena * sbl_get_thread_arena(void)
SBL_ARENA_DEF void * sbl_arena_alloc_zero(SblArena *arena, uint64_t size)
SBL_ARENA_DEF SblArenaMark sbl_arena_mark(SblArena *arena)
SBL_ARENA_DEF void sbl_arena_reset(SblArena *arena)
SBL_ARENA_DEF void sbl_arena_free(SblArena *arena)
#define SBL_ARENA_MEMSET(dst, val, sz)
Definition sbl_arena.h:89
SBL_ARENA_DEF bool sbl_arena_init(SblArena *arena, uint64_t initial_size)
SBL_ARENA_DEF void sbl_arena_rewind(SblArena *arena, SblArenaMark mark)
__thread SblArena sbl_thread_arena
#define SBL_ARENA_DEF
Definition sbl_arena.h:14
SBL_ARENA_DEF void * sbl_arena_alloc(SblArena *arena, uint64_t size)
A single block of memory in the arena.
Definition sbl_arena.h:34
uint64_t size
Definition sbl_arena.h:35
uint64_t offset
Definition sbl_arena.h:36
uint64_t _padding
Definition sbl_arena.h:38
struct SblArenaBlock * next
Definition sbl_arena.h:37
Bookmark for arena state.
Definition sbl_arena.h:57
uint64_t offset
Definition sbl_arena.h:59
SblArenaBlock * block
Definition sbl_arena.h:58
Arena allocator.
Definition sbl_arena.h:47
SblArenaBlock * current
Definition sbl_arena.h:49
SblArenaBlock * head
Definition sbl_arena.h:48