diff options
author | 3gg <3gg@shellblade.net> | 2023-07-17 09:06:14 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2023-07-17 09:06:14 -0700 |
commit | ced89ff7989fde2f3d1828c9be70600d70d72e3d (patch) | |
tree | 8c27f6243325f090b08e678e5e28b2055adffcef /mempool/include | |
parent | 7ab7d7d5b836d2595c5dc2c6db90c489f6768246 (diff) |
Add used list to mempool; fix mem iteration.
Diffstat (limited to 'mempool/include')
-rw-r--r-- | mempool/include/mempool.h | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/mempool/include/mempool.h b/mempool/include/mempool.h index 23786b3..bd4d4dd 100644 --- a/mempool/include/mempool.h +++ b/mempool/include/mempool.h | |||
@@ -91,28 +91,43 @@ | |||
91 | /// The caller can use 'i' as the index of the current block. | 91 | /// The caller can use 'i' as the index of the current block. |
92 | /// | 92 | /// |
93 | /// It is valid to mempool_free() the object at each step of the iteration. | 93 | /// It is valid to mempool_free() the object at each step of the iteration. |
94 | #define mempool_foreach(POOL, ITER, BODY) \ | 94 | #define mempool_foreach(POOL, ITER, BODY) \ |
95 | for (size_t i = 0; i < (POOL)->pool.num_blocks; ++i) { \ | 95 | { \ |
96 | if (!(POOL)->pool.block_info[i].used) { \ | 96 | size_t i = (POOL)->pool.used; \ |
97 | continue; \ | 97 | do { \ |
98 | } \ | 98 | if ((POOL)->pool.block_info[i].used) { \ |
99 | __typeof__((POOL)->object[0])* ITER = \ | 99 | __typeof__((POOL)->object[0])* ITER = \ |
100 | &(((__typeof__((POOL)->object[0])*)(POOL)->pool.blocks))[i]; \ | 100 | &(((__typeof__((POOL)->object[0])*)(POOL)->pool.blocks))[i]; \ |
101 | (void)ITER; \ | 101 | (void)ITER; \ |
102 | BODY; \ | 102 | BODY; \ |
103 | } \ | ||
104 | const size_t next = (POOL)->pool.block_info[i].next_used; \ | ||
105 | if (next == i) { \ | ||
106 | break; \ | ||
107 | } \ | ||
108 | i = next; \ | ||
109 | } while (true); \ | ||
103 | } | 110 | } |
104 | 111 | ||
105 | // ----------------------------------------------------------------------------- | 112 | // ----------------------------------------------------------------------------- |
106 | 113 | ||
107 | typedef struct BlockInfo { | 114 | typedef struct BlockInfo { |
108 | size_t next; /// For free blocks, points to the next free block. | 115 | size_t next_free; /// For free blocks, points to the next free block. |
116 | size_t next_used; /// For used blocks, points to the next used block. | ||
109 | bool used; | 117 | bool used; |
110 | } BlockInfo; | 118 | } BlockInfo; |
111 | 119 | ||
120 | /// Memory pool. | ||
121 | /// | ||
122 | /// 'head' and 'used' always points to a valid block (e.g., 0). | ||
123 | /// The implementation must check whether the head of the lists are used/free. | ||
124 | /// For example, iteration must stop when it finds the first unused block | ||
125 | /// (BlockInfo.used == 0). | ||
112 | typedef struct mempool { | 126 | typedef struct mempool { |
113 | size_t block_size_bytes; | 127 | size_t block_size_bytes; |
114 | size_t num_blocks; | 128 | size_t num_blocks; |
115 | size_t head; /// Points to the first block in the free list. | 129 | size_t head; /// Points to the first block in the free list. |
130 | size_t used; /// Points to the first block in the used list. | ||
116 | bool dynamic; /// True if blocks and info are dynamically-allocated. | 131 | bool dynamic; /// True if blocks and info are dynamically-allocated. |
117 | BlockInfo* block_info; | 132 | BlockInfo* block_info; |
118 | uint8_t* blocks; | 133 | uint8_t* blocks; |