From 2a016de1c2eb45fc5f9c8cebf6b3c726b01ec340 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Tue, 11 Jul 2023 18:37:31 -0700 Subject: Add support for dynamically allocated mempools. --- mempool/include/mempool.h | 76 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'mempool/include') diff --git a/mempool/include/mempool.h b/mempool/include/mempool.h index a0b3a33..2447884 100644 --- a/mempool/include/mempool.h +++ b/mempool/include/mempool.h @@ -1,3 +1,16 @@ +/* + * Block/Pool Allocator. + * + * Clients should use the macros to define and use pools. They make the API + * type-safe. + * + * The pool allocator works on one big chunk of memory, which can be statically + * or dynamically allocated. This chunk is divided into fixed-sized blocks. + * Allocation/deallocation happens with block granularity. + * + * Block information is stored in a separate array so that client data is + * contiguous in the main pool of memory and better cached. + */ #pragma once #include @@ -5,7 +18,7 @@ #include #include -/// Define a typed mempool of the given number of blocks. +/// Define a statically-allocated, typed pool of the given number of blocks. #define DEF_MEMPOOL(POOL, TYPE, NUM_BLOCKS) \ typedef struct POOL { \ mempool pool; \ @@ -13,7 +26,15 @@ TYPE blocks[NUM_BLOCKS]; \ } POOL; -/// Create a new pool. +/// Define a dynamically-allocated, typed pool. +#define DEF_MEMPOOL_DYN(POOL, TYPE) \ + typedef struct POOL { \ + mempool pool; \ + BlockInfo* block_info; \ + TYPE* blocks; \ + } POOL; + +/// Initialize a statically-allocated pool. #define mempool_make(POOL) \ { \ assert(POOL); \ @@ -24,8 +45,24 @@ block_size); \ } +/// Initialize a dynamically-allocated pool. +#define mempool_make_dyn(POOL, num_blocks, block_size) \ + mempool_make_(&(POOL)->pool, 0, 0, num_blocks, block_size) + +/// Destroy the pool. +/// +/// If the pool is dynamically allocated, then this function frees its memory. +#define mempool_del(POOL) mempool_del_(&(POOL)->pool) + +/// Clear the pool. +/// +/// This function frees all of the pool's blocks. The resulting pool is as if it +/// were newly created. +#define mempool_clear(POOL) mempool_clear_(&(POOL)->pool) + /// Allocate a new block. /// Return 0 if there is no memory left. +/// New blocks are conveniently zeroed out. #define mempool_alloc(POOL) mempool_alloc_(&(POOL)->pool) /// Free the block. @@ -60,6 +97,8 @@ BODY; \ } +// ----------------------------------------------------------------------------- + typedef struct BlockInfo { bool used; } BlockInfo; @@ -69,29 +108,28 @@ typedef struct mempool { size_t num_blocks; size_t next_free_block; bool full; + bool dynamic; // True if blocks and info are dynamically-allocated. 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. +/// Create a pool allocator. +/// +/// 'BlockInfo' and 'blocks' may be user-provided (static pool) or null (dynamic +/// pool). +/// - If null, the pool malloc()s the memory for them. +/// - If given: +/// - `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_( +bool 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. +void mempool_del_(mempool*); +void mempool_clear_(mempool*); +void* mempool_alloc_(mempool*); +void mempool_free_(mempool*, void** block_ptr); +void* mempool_get_block_(const mempool*, size_t block_index); size_t mempool_get_block_index_(const mempool*, const void* block); -- cgit v1.2.3