#ifndef LPOOL_H_ #define LPOOL_H_ #include #include #ifdef __cplusplus extern "C" { #endif typedef union LPoolBlock LPoolBlock; union LPoolBlock { uint32_t next; // offset from start to next free block (when not allocated) unsigned char data[0]; // data when allocated }; /** @file * Pool allocator. * * An LPool 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 LPool LPool; struct LPool { LPoolBlock *free_list; // free list uint8_t *start; // start of user buffer uint8_t *end; // one past end of user buffer uint32_t block_size; // aligned size of each block uint32_t capacity; // number of blocks uint32_t align; // alignment }; /** Initialize the pool. * * Block size will be rounded up by alignment, or to size of a pointer if alignment is less that a pointer. * Prefer to use lock sizes that's pointer aligned * * @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 lpool_init(LPool *pool, void *buffer, size_t buffer_size, uint32_t block_size, uint32_t alignment); // Allocate a block from the pool. Returns NULL if no more space [[gnu::assume_aligned(_Alignof(LPoolBlock))]] void *lpool_alloc(LPool *pool); // Free @p . Returns memory to the pool void lpool_free(LPool *pool, void *p); // Frees all memory in the pool, resetting it to initial state. void lpool_reset(LPool *pool); #ifdef __cplusplus } // extern "C" #endif #endif