#pragma once #include "list.h" #include #include #include /// Define a typed listpool of a given size. #define DEF_LISTPOOL(POOL, TYPE, NUM_BLOCKS) \ typedef struct POOL { \ listpool pool; \ list nodes[NUM_BLOCKS]; \ TYPE blocks[NUM_BLOCKS]; \ } POOL; /// Creates a new listpool. #define listpool_make(POOL) \ { \ assert(POOL); \ const size_t block_size = sizeof((POOL)->blocks[0]); \ const size_t num_blocks = sizeof((POOL)->blocks) / block_size; \ listpool_make_( \ &(POOL)->pool, (POOL)->nodes, (POOL)->blocks, num_blocks, block_size); \ } /// Allocate a new block. /// Return 0 if there is no memory left. #define listpool_alloc(POOL) listpool_alloc_(&(POOL)->pool) /// Free the block. /// The block pointer is conveniently set to 0. #define listpool_free(POOL, ITEM) listpool_free_(&(POOL)->pool, (void**)ITEM) /// Remove a value from the list. /// Defined here instead of DEF_LISTPOOL_IMPL() because not all types may have /// an operator==. #define listpool_remove(POOL, VAL) \ { \ listpool_foreach(POOL, iter, { \ if (*iter == VAL) { \ listpool_free(POOL, &iter); \ break; \ } \ }); \ } /// Iterate over the used items of the pool. #define listpool_foreach(POOL, ITER, BODY) \ for (list* it_ = (POOL)->pool.used; it_; it_ = it_->next) { \ typeof((POOL)->blocks[0])* ITER = \ &(POOL)->blocks[it_ - (POOL)->pool.nodes]; \ (void)ITER; \ BODY; \ } typedef struct listpool { size_t block_size_bytes; size_t num_blocks; list* free; // Head of the free list. list* used; // Head of the used list. list* nodes; // Array of nodes. uint8_t* blocks; // Array of blocks; } listpool; /// Create a new list pool from a user-provided array of memory. /// `nodes` must have at least `num_blocks` nodes. /// `blocks` must be at least `num_blocks` * `block_size_bytes` bytes. /// All blocks are zeroed out for convenience. void listpool_make_( listpool* pool, list* nodes, void* blocks, size_t num_blocks, size_t block_size_bytes); /// Allocate a new block. /// Return 0 if there is no memory left. void* listpool_alloc_(listpool* pool); /// Free the block. /// The block pointer is conveniently set to 0. void listpool_free_(listpool* pool, void** block_ptr);