24#define restrict __restrict__
40#define PASTE(a, b) a##b
48#define XPASTE(a, b) PASTE(a, b)
56#define JOIN(a, b) XPASTE(a, XPASTE(_, b))
67#define IS_POW2(X) ((X) != 0 && ((X) & ((X) - 1)) == 0)
78#error "Must define NAME."
79#define FUNCTION_DEFINITIONS
80#define TYPE_DEFINITIONS
82#define ARENA_NAME NAME
89#ifndef FUNCTION_LINKAGE
90#define FUNCTION_LINKAGE
94#define ARENA_TYPE struct ARENA_NAME
95#define ARENA_STATE_TYPE struct JOIN(ARENA_NAME, state)
103struct JOIN(ARENA_NAME, state);
109#ifdef TYPE_DEFINITIONS
124struct JOIN(ARENA_NAME, state) {
157FUNCTION_LINKAGE void JOIN(ARENA_NAME, init)(
void *self_,
const size_t len,
unsigned char *backing_buf);
183FUNCTION_LINKAGE void *
JOIN(ARENA_NAME, allocate_aligned)(
void *self_,
const size_t alignment,
const size_t size);
210FUNCTION_LINKAGE void *
JOIN(ARENA_NAME, reallocate_aligned)(
void *self_,
void *old_ptr_,
const size_t alignment,
211 const size_t old_size,
const size_t new_size);
225FUNCTION_LINKAGE void *
JOIN(ARENA_NAME, reallocate)(
void *self_,
void *old_ptr,
const size_t old_size,
226 const size_t new_size);
236#ifdef FUNCTION_DEFINITIONS
249 ARENA_STATE_TYPE curr_state;
250 curr_state.arena_ptr = arena_ptr;
251 curr_state.prev_offset = arena_ptr->prev_offset;
252 curr_state.curr_offset = arena_ptr->curr_offset;
258 prev_state.arena_ptr->prev_offset = prev_state.prev_offset;
259 prev_state.arena_ptr->curr_offset = prev_state.curr_offset;
267 ARENA_TYPE *self = (ARENA_TYPE *)self_;
269 const uintptr_t padding = calc_alignment_padding(
alignof(max_align_t), (uintptr_t)backing_buf);
271 assert(len >= padding);
273 self->buf_ptr = &backing_buf[padding];
274 self->buf_len = len - padding;
275 self->curr_offset = 0;
276 self->prev_offset = 0;
283 ARENA_TYPE *self = (ARENA_TYPE *)self_;
285 self->curr_offset = 0;
286 self->prev_offset = 0;
297FUNCTION_LINKAGE void *
JOIN(ARENA_NAME, allocate_aligned)(
void *self_,
const size_t alignment,
const size_t size)
301 ARENA_TYPE *self = (ARENA_TYPE *)self_;
303 void *ptr = (
void *)&self->buf_ptr[self->curr_offset];
305 size_t space_left = self->buf_len - (size_t)self->curr_offset;
307 const bool has_space_left = align(alignment, size, &ptr, &space_left);
308 if (!has_space_left) {
312 const uintptr_t relative_offset = (uintptr_t)((
unsigned char *)ptr - &self->buf_ptr[0]);
314 self->prev_offset = relative_offset;
315 self->curr_offset = relative_offset + size;
317 memset(ptr, 0, size);
326 return JOIN(ARENA_NAME, allocate_aligned)(self_,
alignof(max_align_t), size);
330static inline void *
JOIN(
JOIN(internal, ARENA_NAME),
331 try_optimizing_w_prev_offset)(ARENA_TYPE *self,
unsigned char *old_ptr,
const size_t old_size,
332 const size_t new_size)
334 if (&self->buf_ptr[self->prev_offset] != old_ptr) {
338 self->curr_offset = self->prev_offset + new_size;
340 if (new_size > old_size) {
341 const size_t diff = new_size - old_size;
343 memset(&self->buf_ptr[self->curr_offset], 0, diff);
350FUNCTION_LINKAGE void *
JOIN(ARENA_NAME, reallocate_aligned)(
void *self_,
void *old_ptr_,
const size_t alignment,
351 const size_t old_size,
const size_t new_size)
356 ARENA_TYPE *self = (ARENA_TYPE *)self_;
357 unsigned char *old_ptr = (
unsigned char *)old_ptr_;
359 const bool misc_input = old_ptr == NULL || old_size == 0 || new_size == 0;
360 const bool inside_arena_buf = &self->buf_ptr[0] <= old_ptr && old_ptr <= &self->buf_ptr[self->buf_len - 1];
361 if (misc_input || !inside_arena_buf) {
365 const bool has_optimized_w_prev_buf =
366 JOIN(
JOIN(internal, ARENA_NAME), try_optimizing_w_prev_offset)(self, old_ptr, old_size, new_size);
367 if (has_optimized_w_prev_buf) {
371 const size_t copy_size = old_size < new_size ? old_size : new_size;
373 void *new_mem =
JOIN(ARENA_NAME, allocate_aligned)(self, alignment, new_size);
375 memmove(new_mem, old_ptr, copy_size);
381 const size_t new_size)
385 return JOIN(ARENA_NAME, reallocate_aligned)(self_, old_ptr,
alignof(max_align_t), old_size, new_size);
395#undef FUNCTION_LINKAGE
396#undef FUNCTION_DEFINITIONS
397#undef TYPE_DEFINITIONS
401#undef ARENA_STATE_TYPE
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition arena_template.h:56
#define IS_POW2(X)
Macro to check if a number is a power of two.
Definition arena_template.h:67
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:145
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition fstack_template.h:50
size_t curr_offset
Arena curr offset.
Definition arena_template.h:127
size_t prev_offset
Arena prev offset.
Definition arena_template.h:126
arena_type * arena_ptr
Arena pointer.
Definition arena_template.h:125
unsigned char * buf_ptr
Underlying buffer pointer.
Definition arena_template.h:118
size_t prev_offset
Previous offset relative to buf_ptr.
Definition arena_template.h:116
size_t buf_len
Underlying buffer length.
Definition arena_template.h:115
size_t curr_offset
Current offset relative to buf_ptr.
Definition arena_template.h:117