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. --- listpool/include/listpool.h | 79 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 listpool/include/listpool.h (limited to 'listpool/include/listpool.h') diff --git a/listpool/include/listpool.h b/listpool/include/listpool.h new file mode 100644 index 0000000..a5e4955 --- /dev/null +++ b/listpool/include/listpool.h @@ -0,0 +1,79 @@ +#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); -- cgit v1.2.3