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/src/listpool.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 listpool/src/listpool.c (limited to 'listpool/src/listpool.c') diff --git a/listpool/src/listpool.c b/listpool/src/listpool.c new file mode 100644 index 0000000..9c86a3b --- /dev/null +++ b/listpool/src/listpool.c @@ -0,0 +1,78 @@ +#include "listpool.h" + +#include + +void listpool_make_(listpool* pool, list* nodes, void* blocks, + size_t num_blocks, size_t block_size_bytes) { + assert(pool); + pool->block_size_bytes = block_size_bytes; + pool->num_blocks = num_blocks; + pool->free = &nodes[0]; + pool->used = 0; + pool->nodes = nodes; + pool->blocks = blocks; + list_make(nodes, num_blocks); + memset(blocks, 0, num_blocks * block_size_bytes); +} + +void* listpool_alloc_(listpool* pool) { + assert(pool); + if (!pool->free) { + return 0; + } + + const size_t index = pool->free - pool->nodes; + assert(index < pool->num_blocks); + + list* free = pool->free; + pool->free = pool->free->next; + + // pool->used is always the head of the used list, so prepend the new item to + // the list. + list* new_used = free; + new_used->prev = 0; + new_used->next = pool->used; + if (pool->used) { + pool->used->prev = new_used; + } + pool->used = new_used; + + return pool->blocks + index * pool->block_size_bytes; +} + +void listpool_free_(listpool* pool, void** block_ptr) { + assert(pool); + assert(block_ptr); + + memset(*block_ptr, 0, pool->block_size_bytes); + + const size_t index = + ((uint8_t*)*block_ptr - pool->blocks) / pool->block_size_bytes; + assert(index < pool->num_blocks); + + list* item = &pool->nodes[index]; + + // We must remove the item from the used list first. + if (item->prev) { + item->prev->next = item->next; + } + if (item->next) { + item->next->prev = item->prev; + } + if (item == pool->used) { + pool->used = item->next; + } + + // pool->free is always the head of the free list, so prepend the new item to + // the list. The item is now free to wire after removing it from the used + // list. + if (!pool->free) { + pool->free = item; + } else { + item->next = pool->free; + pool->free->prev = item; + pool->free = item; + } + + *block_ptr = 0; +} -- cgit v1.2.3