arena.h (1647B)
1 #ifndef ARENA_H 2 #define ARENA_H 3 4 #include <assert.h> 5 #include <stdalign.h> 6 #include <stddef.h> 7 #include <stdint.h> 8 9 /* helper macros to allow us to use bitwise tricks to quickly and efficiently 10 * calculate aligned addresses and sizes. 11 */ 12 #define IS_POW2(v) (((v) & ((v) - 1)) == 0) 13 #define IS_ALIGNED(v, align) (((v) & ((align) - 1)) == 0) 14 #define ALIGN_PREV(v, align) ((v) & ~((align) - 1)) 15 #define ALIGN_NEXT(v, align) ALIGN_PREV(((v) + ((align) - 1)), (align)) 16 17 struct arena { 18 void *ptr; 19 uint64_t cap, len; 20 }; 21 22 /* arenas dont support freeing individual elements, instead allowing only to 23 * free all elements at once. 24 */ 25 inline void 26 arena_reset(struct arena *arena) 27 { 28 arena->len = 0; 29 } 30 31 /* we might want to allocate arbitrary buffers out of an arena, with any given 32 * alignment (as long as it is a power of two). 33 */ 34 inline void * 35 arena_alloc(struct arena *arena, size_t size, size_t align) 36 { 37 assert(size); 38 assert(align); 39 assert(IS_POW2(align)); 40 41 uintptr_t aligned_ptr = ALIGN_NEXT((uintptr_t) arena->ptr + arena->len, align); 42 if (aligned_ptr + size > (uintptr_t) arena->ptr + arena->cap) 43 return NULL; 44 45 arena->len = (aligned_ptr - (uintptr_t) arena->ptr) + size; 46 47 return (void *) aligned_ptr; 48 } 49 50 /* helper macros to make allocation more concise. 51 */ 52 #define ARENA_ALLOC_ARRAY(arena, T, n) \ 53 ((T *) arena_alloc((arena), sizeof(T) * (n), alignof(T))) 54 55 #define ARENA_ALLOC_SIZED(arena, T) \ 56 ARENA_ALLOC_ARRAY((arena), T, 1) 57 58 #endif /* ARENA_H */ 59 60 #ifdef HEADER_IMPL 61 62 extern inline void 63 arena_reset(struct arena *arena); 64 65 extern inline void * 66 arena_alloc(struct arena *arena, size_t size, size_t align); 67 68 #endif /* HEADER_IMPL */