solidc
Robust collection of general-purpose cross-platform C libraries and data structures designed for rapid and safe development in C
Loading...
Searching...
No Matches
arena.h
1
21#ifndef ARENA_H
22#define ARENA_H
23
24#include <stdbool.h>
25#include <stddef.h>
26#include <stdint.h>
27#include <string.h>
28
29#if defined(__cplusplus)
30extern "C" {
31#endif
32
33#ifdef _MSC_VER
34#include <intrin.h>
35#define ARENA_INLINE __forceinline
36#define ARENA_PREFETCH(addr) _mm_prefetch((const char*)(addr), _MM_HINT_T0)
37#define ARENA_LIKELY(x) (x)
38#define ARENA_UNLIKELY(x) (x)
39#define ARENA_ALIGNED(n) __declspec(align(n))
40#else
41#define ARENA_INLINE inline __attribute__((always_inline))
42#define ARENA_PREFETCH(addr) __builtin_prefetch((addr), 1, 3)
43#define ARENA_LIKELY(x) __builtin_expect(!!(x), 1)
44#define ARENA_UNLIKELY(x) __builtin_expect(!!(x), 0)
45#define ARENA_ALIGNED(n) __attribute__((aligned(n)))
46#endif
47
49#define ARENA_DEFAULT_ALIGN 16
50
52#define ARENA_MIN_BLOCK_SIZE (64 * 1024)
53
62typedef struct ArenaBlock {
63 struct ArenaBlock* next;
64 char* base;
65 char* end;
68
74typedef struct ARENA_ALIGNED(64) Arena {
75 char* curr;
76 char* end;
77 ArenaBlock* current_block;
78 ArenaBlock* head;
79 size_t page_size;
80 size_t total_committed;
81 bool heap_allocated;
82 ArenaBlock first_block;
83} Arena;
84
95void arena_init(Arena* restrict a, void* restrict buf, size_t size);
96
106Arena* arena_create(size_t reserve_size);
107
113static ARENA_INLINE void arena_reset(Arena* restrict a) {
114 if (!a || !a->head) return;
115 a->current_block = a->head;
116 a->curr = a->head->base;
117 a->end = a->head->end;
118}
119
125void arena_destroy(Arena* restrict arena);
126
128static ARENA_INLINE size_t arena_committed_size(const Arena* restrict a) { return a->total_committed; }
129
135static ARENA_INLINE size_t arena_used_size(const Arena* restrict a) {
136 if (!a || !a->current_block) return 0;
137 size_t block_capacity = (size_t)(a->current_block->end - a->current_block->base);
138 size_t block_used = (size_t)(a->curr - a->current_block->base);
139 return (a->total_committed - block_capacity) + block_used;
140}
141
146void* _arena_alloc_slow(Arena* restrict arena, size_t size, size_t alignment);
147
154static ARENA_INLINE void* arena_alloc_align(Arena* restrict arena, size_t size, size_t alignment) {
155 if (size == 0) return NULL;
156
157 uintptr_t aligned = ((uintptr_t)arena->curr + alignment - 1) & ~(alignment - 1);
158 uintptr_t next = aligned + size;
159
160 if (ARENA_LIKELY(next <= (uintptr_t)arena->end)) {
161 arena->curr = (char*)next;
162 return (void*)aligned;
163 }
164
165 return _arena_alloc_slow(arena, size, alignment);
166}
167
172static ARENA_INLINE void* arena_alloc(Arena* restrict arena, size_t size) {
173 return arena_alloc_align(arena, size, ARENA_DEFAULT_ALIGN);
174}
175
181static ARENA_INLINE void* arena_alloc_unaligned(Arena* restrict arena, size_t size) {
182 if (size == 0) return NULL;
183
184 char* ptr = arena->curr;
185 char* next = ptr + size;
186
187 if (ARENA_LIKELY(next <= arena->end)) {
188 arena->curr = next;
189 return ptr;
190 }
191
192 return _arena_alloc_slow(arena, size, 1);
193}
194
196#define ARENA_ALLOC(arena, type) ((type*)arena_alloc_align((arena), sizeof(type), _Alignof(type)))
197
199#define ARENA_ALLOC_ARRAY(arena, type, count) \
200 ((type*)arena_alloc_align((arena), sizeof(type) * (count), _Alignof(type)))
201
203static ARENA_INLINE void* arena_alloc_zero(Arena* restrict arena, size_t size, size_t alignment) {
204 void* ptr = arena_alloc_align(arena, size, alignment);
205 if (ptr) memset(ptr, 0, size);
206 return ptr;
207}
208
210static ARENA_INLINE void* arena_alloc_array_zero(Arena* restrict arena, size_t size, size_t alignment, size_t count) {
211 void* ptr = arena_alloc_align(arena, size * count, alignment);
212 if (ptr) memset(ptr, 0, size * count);
213 return ptr;
214}
215
217#define ARENA_ALLOC_ZERO(arena, type) ((type*)arena_alloc_zero((arena), sizeof(type), _Alignof(type)))
218
220#define ARENA_ALLOC_ARRAY_ZERO(arena, type, count) \
221 ((type*)arena_alloc_array_zero((arena), sizeof(type), _Alignof(type), (count)))
222
232static ARENA_INLINE bool arena_alloc_batch(Arena* restrict arena, const size_t* restrict sizes, size_t count,
233 void** restrict out_ptrs) {
234 if (!arena || !sizes || !out_ptrs || count == 0) return false;
235
236 const size_t mask = ARENA_DEFAULT_ALIGN - 1;
237 size_t total = 0;
238 for (size_t i = 0; i < count; ++i) {
239 total = (total + mask) & ~mask;
240 total += sizes[i];
241 }
242
243 char* base = (char*)arena_alloc(arena, total);
244 if (!base) return false;
245
246 char* cur = base;
247 for (size_t i = 0; i < count; ++i) {
248 cur = (char*)(((uintptr_t)cur + mask) & ~mask);
249 out_ptrs[i] = cur;
250 cur += sizes[i];
251 }
252
253 return true;
254}
255
260static ARENA_INLINE char* arena_strdup(Arena* restrict arena, const char* restrict str) {
261 if (!arena || !str) return NULL;
262 size_t len = strlen(str);
263 char* dup = (char*)arena_alloc_unaligned(arena, len + 1);
264 if (!dup) return NULL;
265 memcpy(dup, str, len + 1);
266 return dup;
267}
268
274static ARENA_INLINE char* arena_strdupn(Arena* restrict arena, const char* restrict str, size_t length) {
275 if (!arena || !str) return NULL;
276 char* dup = (char*)arena_alloc_unaligned(arena, length + 1);
277 if (!dup) return NULL;
278 memcpy(dup, str, length);
279 dup[length] = '\0';
280 return dup;
281}
282
283#if defined(__cplusplus)
284}
285#endif
286
287#endif // ARENA_H
char * end
Definition arena.h:65
bool is_static
Definition arena.h:66