#ifndef UC_SARENA_H_ #define UC_SARENA_H_ #include #include #ifdef __cplusplus extern "C" { #endif /** @file * Static arena allocator. * * An UCSArena allocates memory from pre-existing array * * The backing array should be suitable aligned to the types * that will be allocated from it. Use .e.g * @code * _Alignas(16) char mem[1024]; * @endcode * as the backing array. * * Once allocated, a piece of memory obtained from the * allocator cannot be free'd individually, only the entire SArena can * be free'd/reset */ typedef struct UCSArena UCSArena; struct UCSArena { char *start; // start of user buffer char *curr; // next alloc point char *end; // one past end of user buffer }; /** Initialize a UCSArena with predefined backing array. * @data must be an array type * Use as * @code * _Alignas(16) char v[128]; * SArana a = UC_BV_STATIC_INIT(v); * @endcode */ #define UC_SAR_STATIC_INIT(data)\ UC_SAR_INIT((data), sizeof(data)) /** Initialize a UCSArena with predefined memory * Use as * @code * char v[128]; * SArana a = UC_BV_STATIC_INIT(v, sizeof v); * @endcode * or * @code * char *m = malloc(128); * SArana a = UC_BV_INIT(m, 128); * @endcode */ #define UC_SAR_INIT(data, sz)\ {\ (data),\ (data),\ (data) + sz\ } /** Initialize a UCSArena with an array as the backing memory to allocate from. * The macro can be used at local scope to allocate memory automatic (stack) storage, * or at global scope where the backing array will have static storage duration * * Use as: * @code * UC_SAR_ALLOC_DEF(my_allocator, 1024) * struct foo *foo = uc_sar_alloc(&my_allocator); * if (foo == NULL) { * // out of memory * } * @endcode * * @note, the backing store has alignment of 16. Use manual init if a different alignment * is needed. * @param var_name Variable name for the allocator * @param size_ byte size of the backing array */ #define UC_SAR_ALLOC_DEF(var_name, size_) \ struct {\ _Alignas(16) char memory[size_]; \ } var_name ## _memory;\ UCSArena var_name = UC_SAR_STATIC_INIT(var_name ## _memory.memory) /** Allocate space for @type_ , returned memory is aligned to requirements * of @type. * * Use as: * @code * UC_SAR_ALLOC_DEF(my_allocator, 1024) * struct foo *foo = UC_SAR_ALLOC_ALIGNED(&my_allocator, struct foo); * // Array types can be used too, room for null terminated string of lengh 10: * char *str = UC_SAR_ALLOC_ALIGNED(&my_allocator, char[11]); * @endcode */ #define UC_SAR_ALLOC_ALIGNED(allocator, type_) \ uc_sar_alloc_aligned((allocator), sizeof (type_), _Alignof(type_)) // Allocate @sz bytes from the UCSArena. Returns NULL if not enough space void *uc_sar_alloc(UCSArena *a, size_t sz); // Allocate @sz bytes from the UCSArena, returned pointer is aligned to @align // Returns NULL if not enough space void *uc_sar_alloc_aligned(UCSArena *a, size_t sz, unsigned int align); static inline void uc_sar_reset(UCSArena *a) { a->curr = a->start; } #ifdef __cplusplus } #endif #endif