From f8217d240d598f39f70047f7a623dd46312542c6 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 4 Dec 2021 16:01:12 -0800 Subject: Initial commit. --- mempool/include/mempool.h | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 mempool/include/mempool.h (limited to 'mempool/include/mempool.h') diff --git a/mempool/include/mempool.h b/mempool/include/mempool.h new file mode 100644 index 0000000..41d56e5 --- /dev/null +++ b/mempool/include/mempool.h @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include +#include + +/// Define a typed mempool of the given number of blocks. +#define DEF_MEMPOOL(POOL, TYPE, NUM_BLOCKS) \ + typedef struct POOL { \ + mempool pool; \ + BlockInfo block_info[NUM_BLOCKS]; \ + TYPE blocks[NUM_BLOCKS]; \ + } POOL; + +/// Create a new pool. +#define mempool_make(POOL) \ + { \ + assert(POOL); \ + const size_t block_size = sizeof((POOL)->blocks[0]); \ + const size_t num_blocks = sizeof((POOL)->blocks) / block_size; \ + mempool_make_(&(POOL)->pool, (POOL)->block_info, (POOL)->blocks, \ + num_blocks, block_size); \ + } + +/// Allocate a new block. +/// Return 0 if there is no memory left. +#define mempool_alloc(POOL) mempool_alloc_(&(POOL)->pool) + +/// Free the block. +/// The block pointer is conveniently set to 0. +#define mempool_free(POOL, BLOCK_PTR) \ + assert(*BLOCK_PTR); \ + mempool_free_(&(POOL)->pool, (void**)BLOCK_PTR) + +/// Return the ith block. +/// The block must have been allocated. +#define mempool_get_block(POOL, INDEX) \ + ((typeof((POOL)->blocks[0])*)mempool_get_block_(&(POOL)->pool, INDEX)) + +/// Get the index to the given block. +#define mempool_get_block_index(POOL, BLOCK_PTR) \ + mempool_get_block_index_(&(POOL)->pool, BLOCK_PTR) + +/// Iterate over the used blocks of the pool. +#define mempool_foreach(POOL, ITER, BODY) \ + for (size_t i = 0; \ + i < (sizeof((POOL)->blocks) / sizeof(typeof((POOL)->blocks[0]))); \ + ++i) { \ + if (!(POOL)->block_info[i].used) { \ + continue; \ + } \ + typeof((POOL)->blocks[0])* ITER = &(POOL)->blocks[i]; \ + (void)ITER; \ + BODY; \ + } + +typedef struct BlockInfo { + bool used; +} BlockInfo; + +typedef struct mempool { + size_t block_size_bytes; + size_t num_blocks; + size_t next_free_block; + bool full; + BlockInfo* block_info; + uint8_t* blocks; +} mempool; + +/// Create a pool allocator from user-provided memory. +/// `BlockInfo` must hold at least `num_blocks` entries. +/// `blocks` must be at least `num_blocks` * `block_size_bytes` bytes. +/// All blocks are zeroed out for convenience. +void mempool_make_(mempool*, BlockInfo*, void* blocks, size_t num_blocks, + size_t block_size_bytes); + +/// Allocate a new block. +/// Return 0 if there is no memory left. +void* mempool_alloc_(mempool*); + +/// Free the block. +/// The block pointer is conveniently set to 0. +void mempool_free_(mempool*, void** block_ptr); + +/// Return the ith block. +/// The block must have been allocated. +void* mempool_get_block_(const mempool*, size_t block_index); + +/// Get the index to the given block. +size_t mempool_get_block_index_(const mempool*, const void* block); -- cgit v1.2.3