#ifndef UC_SPOOL_H_ #define UC_SPOOL_H_ #include #include #ifdef __cplusplus extern "C" { #endif typedef union UCPoolBlock UCPoolBlock; union UCPoolBlock { UCPoolBlock *next; // next free block (when not allocated) unsigned char data[0]; // data when allocated }; /** @file * Static pool allocator. * * An UCPool allocates fixed size memory chunks from a provided buffer, * and memory allocations can be free'd in any order. * * 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 buffer. * */ typedef struct UCPool UCPool; struct UCPool { UCPoolBlock *free_list; // free list size_t block_size; // aligned size of each block size_t capacity; // number of blocks size_t align; // alignment UCPoolBlock *start; // start of user buffer UCPoolBlock *end; // one past end of user buffer }; /** Initialize the pool. * * Block size will be rounded up by alignment, or to size of a pointer * * @param buffer backing buffer for the pool * @param buffer_size size of @buffer * @param block_size size of each allocation. * @param alignment alignment of each block (must be power of 2) */ void uc_pool_init(UCPool *pool, void *buffer, size_t buffer_size, size_t block_size, size_t alignment); // Allocate a block from the pool. Returns NULL if no more space [[gnu::assume_aligned(_Alignof(UCPoolBlock))]] void *uc_pool_alloc(UCPool *pool); // Free @p . Returns memory to the pool void uc_pool_free(UCPool *pool, void *p); void uc_pool_reset(UCPool *pool); #ifdef __cplusplus } #endif #endif