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; |
