From 470a25323ca89ffa3b0b697aeddcf184d12a1382 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Mon, 23 Jan 2023 18:32:49 -0800 Subject: Update listpool's interface to be on par with mempool's. --- listpool/include/listpool.h | 32 ++++++++++++++++++++++++++------ listpool/src/listpool.c | 13 +++++++++++++ listpool/test/listpool_test.c | 17 +++++++++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/listpool/include/listpool.h b/listpool/include/listpool.h index 1711449..85a3b27 100644 --- a/listpool/include/listpool.h +++ b/listpool/include/listpool.h @@ -45,13 +45,26 @@ }); \ } +/// Return the ith block. +/// The block must have been allocated. +#define listpool_get_block(POOL, INDEX) \ + ((typeof((POOL)->blocks[0])*)listpool_get_block_(&(POOL)->pool, INDEX)) + +/// Get the index to the given block. +#define listpool_get_block_index(POOL, BLOCK_PTR) \ + listpool_get_block_index_(&(POOL)->pool, BLOCK_PTR) + /// 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; \ +/// +/// The caller can use 'i' as the index of the current block. +/// +/// It is valid to mempool_free() the object at each step of the iteration. +#define listpool_foreach(POOL, ITER, BODY) \ + for (list* it_ = (POOL)->pool.used; it_; it_ = it_->next) { \ + const size_t i = it_ - (POOL)->pool.nodes; \ + typeof((POOL)->blocks[0])* ITER = &(POOL)->blocks[i]; \ + (void)ITER; \ + BODY; \ } typedef struct listpool { @@ -78,3 +91,10 @@ void* listpool_alloc_(listpool* pool); /// Free the block. /// The block pointer is conveniently set to 0. void listpool_free_(listpool* pool, void** block_ptr); + +/// Return the ith block. +/// The block must have been allocated. +void* listpool_get_block_(const listpool*, size_t block_index); + +/// Get the index to the given block. +size_t listpool_get_block_index_(const listpool*, const void* block); diff --git a/listpool/src/listpool.c b/listpool/src/listpool.c index 8e49f32..758062c 100644 --- a/listpool/src/listpool.c +++ b/listpool/src/listpool.c @@ -77,3 +77,16 @@ void listpool_free_(listpool* pool, void** block_ptr) { *block_ptr = 0; } + +void* listpool_get_block_(const listpool* pool, size_t block_index) { + assert(pool); + assert(block_index < pool->num_blocks); + return pool->blocks + block_index * pool->block_size_bytes; +} + +size_t listpool_get_block_index_(const listpool* pool, const void* block) { + assert(pool); + const size_t block_byte_index = (const uint8_t*)block - pool->blocks; + assert(block_byte_index % pool->block_size_bytes == 0); + return block_byte_index / pool->block_size_bytes; +} diff --git a/listpool/test/listpool_test.c b/listpool/test/listpool_test.c index cb54d00..7a7b0cf 100644 --- a/listpool/test/listpool_test.c +++ b/listpool/test/listpool_test.c @@ -137,6 +137,23 @@ TEST_CASE(listpool_traverse_full) { TEST_EQUAL(sum(&pool), (NUM_BLOCKS) * (NUM_BLOCKS + 1) / 2); } +// Get the ith (allocated) block. +TEST_CASE(listpool_get_block) { + test_pool pool; + listpool_make(&pool); + + for (int i = 0; i < NUM_BLOCKS; ++i) { + int* block = listpool_alloc(&pool); + TEST_TRUE(block != 0); + *block = i; + TEST_EQUAL(listpool_get_block_index(&pool, block), (size_t)i); + } + + for (int i = 0; i < NUM_BLOCKS; ++i) { + TEST_EQUAL(*listpool_get_block(&pool, i), i); + } +} + // Remove a value from the list. TEST_CASE(listpool_remove_value) { test_pool pool; -- cgit v1.2.3