toys

toys.git
git clone git://git.lenczewski.org/toys.git
Log | Files | Refs | README | LICENSE

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 */