aboutsummaryrefslogtreecommitdiff
path: root/mempool/include
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2023-07-11 18:37:31 -0700
committer3gg <3gg@shellblade.net>2023-07-11 18:37:31 -0700
commit2a016de1c2eb45fc5f9c8cebf6b3c726b01ec340 (patch)
tree17ca4f39a2777b201146d4c5f65f300a7ffeb045 /mempool/include
parent08ec3a7a1fdb16cbb52b05f934bd001ca38bd991 (diff)
Add support for dynamically allocated mempools.
Diffstat (limited to 'mempool/include')
-rw-r--r--mempool/include/mempool.h76
1 files changed, 57 insertions, 19 deletions
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 @@
1/*
2 * Block/Pool Allocator.
3 *
4 * Clients should use the macros to define and use pools. They make the API
5 * type-safe.
6 *
7 * The pool allocator works on one big chunk of memory, which can be statically
8 * or dynamically allocated. This chunk is divided into fixed-sized blocks.
9 * Allocation/deallocation happens with block granularity.
10 *
11 * Block information is stored in a separate array so that client data is
12 * contiguous in the main pool of memory and better cached.
13 */
1#pragma once 14#pragma once
2 15
3#include <assert.h> 16#include <assert.h>
@@ -5,7 +18,7 @@
5#include <stddef.h> 18#include <stddef.h>
6#include <stdint.h> 19#include <stdint.h>
7 20
8/// Define a typed mempool of the given number of blocks. 21/// Define a statically-allocated, typed pool of the given number of blocks.
9#define DEF_MEMPOOL(POOL, TYPE, NUM_BLOCKS) \ 22#define DEF_MEMPOOL(POOL, TYPE, NUM_BLOCKS) \
10 typedef struct POOL { \ 23 typedef struct POOL { \
11 mempool pool; \ 24 mempool pool; \
@@ -13,7 +26,15 @@
13 TYPE blocks[NUM_BLOCKS]; \ 26 TYPE blocks[NUM_BLOCKS]; \
14 } POOL; 27 } POOL;
15 28
16/// Create a new pool. 29/// Define a dynamically-allocated, typed pool.
30#define DEF_MEMPOOL_DYN(POOL, TYPE) \
31 typedef struct POOL { \
32 mempool pool; \
33 BlockInfo* block_info; \
34 TYPE* blocks; \
35 } POOL;
36
37/// Initialize a statically-allocated pool.
17#define mempool_make(POOL) \ 38#define mempool_make(POOL) \
18 { \ 39 { \
19 assert(POOL); \ 40 assert(POOL); \
@@ -24,8 +45,24 @@
24 block_size); \ 45 block_size); \
25 } 46 }
26 47
48/// Initialize a dynamically-allocated pool.
49#define mempool_make_dyn(POOL, num_blocks, block_size) \
50 mempool_make_(&(POOL)->pool, 0, 0, num_blocks, block_size)
51
52/// Destroy the pool.
53///
54/// If the pool is dynamically allocated, then this function frees its memory.
55#define mempool_del(POOL) mempool_del_(&(POOL)->pool)
56
57/// Clear the pool.
58///
59/// This function frees all of the pool's blocks. The resulting pool is as if it
60/// were newly created.
61#define mempool_clear(POOL) mempool_clear_(&(POOL)->pool)
62
27/// Allocate a new block. 63/// Allocate a new block.
28/// Return 0 if there is no memory left. 64/// Return 0 if there is no memory left.
65/// New blocks are conveniently zeroed out.
29#define mempool_alloc(POOL) mempool_alloc_(&(POOL)->pool) 66#define mempool_alloc(POOL) mempool_alloc_(&(POOL)->pool)
30 67
31/// Free the block. 68/// Free the block.
@@ -60,6 +97,8 @@
60 BODY; \ 97 BODY; \
61 } 98 }
62 99
100// -----------------------------------------------------------------------------
101
63typedef struct BlockInfo { 102typedef struct BlockInfo {
64 bool used; 103 bool used;
65} BlockInfo; 104} BlockInfo;
@@ -69,29 +108,28 @@ typedef struct mempool {
69 size_t num_blocks; 108 size_t num_blocks;
70 size_t next_free_block; 109 size_t next_free_block;
71 bool full; 110 bool full;
111 bool dynamic; // True if blocks and info are dynamically-allocated.
72 BlockInfo* block_info; 112 BlockInfo* block_info;
73 uint8_t* blocks; 113 uint8_t* blocks;
74} mempool; 114} mempool;
75 115
76/// Create a pool allocator from user-provided memory. 116/// Create a pool allocator.
77/// `BlockInfo` must hold at least `num_blocks` entries. 117///
78/// `blocks` must be at least `num_blocks` * `block_size_bytes` bytes. 118/// 'BlockInfo' and 'blocks' may be user-provided (static pool) or null (dynamic
119/// pool).
120/// - If null, the pool malloc()s the memory for them.
121/// - If given:
122/// - `BlockInfo` must hold at least `num_blocks` entries.
123/// - `blocks` must be at least `num_blocks` * `block_size_bytes` bytes.
124///
79/// All blocks are zeroed out for convenience. 125/// All blocks are zeroed out for convenience.
80void mempool_make_( 126bool mempool_make_(
81 mempool*, BlockInfo*, void* blocks, size_t num_blocks, 127 mempool*, BlockInfo*, void* blocks, size_t num_blocks,
82 size_t block_size_bytes); 128 size_t block_size_bytes);
83 129
84/// Allocate a new block. 130void mempool_del_(mempool*);
85/// Return 0 if there is no memory left. 131void mempool_clear_(mempool*);
86void* mempool_alloc_(mempool*); 132void* mempool_alloc_(mempool*);
87 133void mempool_free_(mempool*, void** block_ptr);
88/// Free the block. 134void* mempool_get_block_(const mempool*, size_t block_index);
89/// The block pointer is conveniently set to 0.
90void mempool_free_(mempool*, void** block_ptr);
91
92/// Return the ith block.
93/// The block must have been allocated.
94void* mempool_get_block_(const mempool*, size_t block_index);
95
96/// Get the index to the given block.
97size_t mempool_get_block_index_(const mempool*, const void* block); 135size_t mempool_get_block_index_(const mempool*, const void* block);