dsa-c
 
Loading...
Searching...
No Matches
arena_template.h
Go to the documentation of this file.
1
8
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
18#include <assert.h>
19#include <stdalign.h>
20#include <stdbool.h>
21#include <stddef.h>
22#include <stdint.h>
23#include <stdlib.h>
24#include <string.h>
25
26// macro definitions: {{{
27
34#ifndef NAME
35#define FUNCTION_DEFINITIONS
36#define TYPE_DEFINITIONS
37#error "Must define NAME."
38#else
39#define ARENA_NAME NAME
40#endif
41
46#ifndef FUNCTION_LINKAGE
47#define FUNCTION_LINKAGE
48#endif
49
54#ifndef PASTE
55#define PASTE(a, b) a##b
56#endif
57
62#ifndef XPASTE
63#define XPASTE(a, b) PASTE(a, b)
64#endif
65
70#ifndef JOIN
71#define JOIN(a, b) XPASTE(a, XPASTE(_, b))
72#endif
73
81#ifndef IS_POW2
82#define IS_POW2(X) ((X) != 0 && ((X) & ((X) - 1)) == 0)
83#endif
84
86#define ARENA_STATE JOIN(ARENA_NAME, state)
87#define ARENA_TYPE struct ARENA_NAME
88#define ARENA_STATE_TYPE struct ARENA_STATE
90
91// }}}
92
93// type definitions: {{{
94
99#ifdef TYPE_DEFINITIONS
100
104struct ARENA_NAME {
105 size_t buf_len;
106 size_t prev_offset;
107 size_t curr_offset;
108 unsigned char *buf_ptr;
109};
110
114struct JOIN(ARENA_NAME, state) {
115 ARENA_TYPE *arena_ptr;
116 size_t prev_offset;
117 size_t curr_offset;
118};
119
120#endif
121
122// }}}
123
124// function declarations: {{{
125
131FUNCTION_LINKAGE ARENA_STATE_TYPE JOIN(ARENA_NAME, state_save)(ARENA_TYPE *arena_ptr);
132
138FUNCTION_LINKAGE void JOIN(ARENA_NAME, state_restore)(ARENA_STATE_TYPE prev_state);
139
147FUNCTION_LINKAGE void JOIN(ARENA_NAME, init)(ARENA_TYPE *self, const size_t len, unsigned char *backing_buf);
148
154FUNCTION_LINKAGE void JOIN(ARENA_NAME, deallocate_all)(ARENA_TYPE *self);
155
166FUNCTION_LINKAGE void *JOIN(ARENA_NAME, allocate_aligned)(ARENA_TYPE *self, const size_t alignment, const size_t size);
167
177FUNCTION_LINKAGE void *JOIN(ARENA_NAME, allocate)(ARENA_TYPE *self, const size_t size);
178
193FUNCTION_LINKAGE void *JOIN(ARENA_NAME, reallocate_aligned)(ARENA_TYPE *self, void *old_ptr_, const size_t alignment,
194 const size_t old_size, const size_t new_size);
195
208FUNCTION_LINKAGE void *JOIN(ARENA_NAME, reallocate)(ARENA_TYPE *self, void *old_ptr, const size_t old_size,
209 const size_t new_size);
210
211// }}}
212
213// function definitions: {{{
214
219#ifdef FUNCTION_DEFINITIONS
220
221#include "align.h" // align, calc_alignment_padding
222
223FUNCTION_LINKAGE ARENA_STATE_TYPE JOIN(ARENA_NAME, state_save)(ARENA_TYPE *arena_ptr)
224{
225 ARENA_STATE_TYPE curr_state;
226 curr_state.arena_ptr = arena_ptr;
227 curr_state.prev_offset = arena_ptr->prev_offset;
228 curr_state.curr_offset = arena_ptr->curr_offset;
229 return curr_state;
230}
231
232FUNCTION_LINKAGE void JOIN(ARENA_NAME, state_restore)(ARENA_STATE_TYPE prev_state)
233{
234 prev_state.arena_ptr->prev_offset = prev_state.prev_offset;
235 prev_state.arena_ptr->curr_offset = prev_state.curr_offset;
236}
237
238FUNCTION_LINKAGE void JOIN(ARENA_NAME, init)(ARENA_TYPE *self, const size_t len, unsigned char *backing_buf)
239{
240 assert(self);
241 assert(backing_buf);
242
243 const uintptr_t padding = calc_alignment_padding(alignof(max_align_t), (uintptr_t)backing_buf);
244
245 assert(len >= padding);
246
247 self->buf_ptr = &backing_buf[padding];
248 self->buf_len = len - padding;
249 self->curr_offset = 0;
250 self->prev_offset = 0;
251}
252
253FUNCTION_LINKAGE void JOIN(ARENA_NAME, deallocate_all)(ARENA_TYPE *self)
254{
255 assert(self);
256
257 self->curr_offset = 0;
258 self->prev_offset = 0;
259}
260
261FUNCTION_LINKAGE void *JOIN(ARENA_NAME, allocate_aligned)(ARENA_TYPE *self, const size_t alignment, const size_t size)
262{
263 assert(self);
264
265 void *ptr = (void *)&self->buf_ptr[self->curr_offset];
266
267 size_t space_left = self->buf_len - (size_t)self->curr_offset;
268
269 const void* has_space_left = align(alignment, size, &ptr, &space_left);
270 if (!has_space_left) {
271 return NULL;
272 }
273
274 const uintptr_t relative_offset = (uintptr_t)((unsigned char *)ptr - &self->buf_ptr[0]);
275
276 self->prev_offset = relative_offset;
277 self->curr_offset = relative_offset + size;
278
279 memset(ptr, 0, size);
280
281 return ptr;
282}
283
284FUNCTION_LINKAGE void *JOIN(ARENA_NAME, allocate)(ARENA_TYPE *self, const size_t size)
285{
286 assert(self);
287
288 return JOIN(ARENA_NAME, allocate_aligned)(self, alignof(max_align_t), size);
289}
290
292static inline bool JOIN(JOIN(internal, ARENA_NAME),
293 try_optimizing_w_prev_offset)(ARENA_TYPE *self, unsigned char *old_ptr, const size_t old_size,
294 const size_t new_size)
295{
296 if (&self->buf_ptr[self->prev_offset] != old_ptr) {
297 return false;
298 }
299
300 self->curr_offset = self->prev_offset + new_size;
301
302 if (new_size > old_size) {
303 const size_t diff = new_size - old_size;
304
305 memset(&self->buf_ptr[self->curr_offset], 0, diff);
306 }
307
308 return true;
309}
311
312FUNCTION_LINKAGE void *JOIN(ARENA_NAME, reallocate_aligned)(ARENA_TYPE *self, void *old_ptr_, const size_t alignment,
313 const size_t old_size, const size_t new_size)
314{
315 assert(self);
316 assert(IS_POW2(alignment));
317
318 unsigned char *old_ptr = (unsigned char *)old_ptr_;
319
320 const bool misc_input = old_ptr == NULL || old_size == 0 || new_size == 0;
321 const bool inside_arena_buf = &self->buf_ptr[0] <= old_ptr && old_ptr <= &self->buf_ptr[self->buf_len - 1];
322 if (misc_input || !inside_arena_buf) {
323 return NULL;
324 }
325
326 const bool has_optimized_w_prev_buf =
327 JOIN(JOIN(internal, ARENA_NAME), try_optimizing_w_prev_offset)(self, old_ptr, old_size, new_size);
328 if (has_optimized_w_prev_buf) {
329 return old_ptr;
330 }
331
332 const size_t copy_size = old_size < new_size ? old_size : new_size;
333
334 void *new_mem = JOIN(ARENA_NAME, allocate_aligned)(self, alignment, new_size);
335
336 memmove(new_mem, old_ptr, copy_size);
337
338 return new_mem;
339}
340
341FUNCTION_LINKAGE void *JOIN(ARENA_NAME, reallocate)(ARENA_TYPE *self, void *old_ptr, const size_t old_size,
342 const size_t new_size)
343{
344 assert(self);
345
346 return JOIN(ARENA_NAME, reallocate_aligned)(self, old_ptr, alignof(max_align_t), old_size, new_size);
347}
348
349#endif
350
351// }}}
352
353// macro undefs: {{{
354#undef NAME
355#undef FUNCTION_LINKAGE
356#undef FUNCTION_DEFINITIONS
357#undef TYPE_DEFINITIONS
358
359#undef ARENA_NAME
360// }}}
361
362#ifdef __cplusplus
363}
364#endif
365
366// vim: ft=c fdm=marker
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition arena_template.h:71
#define IS_POW2(X)
Macro to check if a number is a power of two.
Definition arena_template.h:82
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:146
size_t curr_offset
Arena curr offset.
Definition arena_template.h:117
size_t prev_offset
Arena prev offset.
Definition arena_template.h:116
arena_type * arena_ptr
Arena pointer.
Definition arena_template.h:115
unsigned char * buf_ptr
Underlying buffer pointer.
Definition arena_template.h:108
size_t prev_offset
Previous offset relative to buf_ptr.
Definition arena_template.h:106
size_t buf_len
Underlying buffer length.
Definition arena_template.h:105
size_t curr_offset
Current offset relative to buf_ptr.
Definition arena_template.h:107