1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
#pragma once
#include "list.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
/// Define a typed listpool of a given size.
#define DEF_LISTPOOL(POOL, TYPE, NUM_BLOCKS) \
typedef struct POOL { \
listpool pool; \
list nodes[NUM_BLOCKS]; \
TYPE blocks[NUM_BLOCKS]; \
} POOL;
/// Creates a new listpool.
#define listpool_make(POOL) \
{ \
assert(POOL); \
const size_t block_size = sizeof((POOL)->blocks[0]); \
const size_t num_blocks = sizeof((POOL)->blocks) / block_size; \
listpool_make_(&(POOL)->pool, (POOL)->nodes, (POOL)->blocks, num_blocks, \
block_size); \
}
/// Allocate a new block.
/// Return 0 if there is no memory left.
#define listpool_alloc(POOL) listpool_alloc_(&(POOL)->pool)
/// Free the block.
/// The block pointer is conveniently set to 0.
#define listpool_free(POOL, ITEM) listpool_free_(&(POOL)->pool, (void**)ITEM)
/// Remove a value from the list.
/// Defined here instead of DEF_LISTPOOL_IMPL() because not all types may have
/// an operator==.
#define listpool_remove(POOL, VAL) \
{ \
listpool_foreach(POOL, iter, { \
if (*iter == VAL) { \
listpool_free(POOL, &iter); \
break; \
} \
}); \
}
/// 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; \
}
typedef struct listpool {
size_t block_size_bytes;
size_t num_blocks;
list* free; // Head of the free list.
list* used; // Head of the used list.
list* nodes; // Array of nodes.
uint8_t* blocks; // Array of blocks;
} listpool;
/// Create a new list pool from a user-provided array of memory.
/// `nodes` must have at least `num_blocks` nodes.
/// `blocks` must be at least `num_blocks` * `block_size_bytes` bytes.
/// All blocks are zeroed out for convenience.
void listpool_make_(listpool* pool, list* nodes, void* blocks,
size_t num_blocks, size_t block_size_bytes);
/// Allocate a new block.
/// Return 0 if there is no memory left.
void* listpool_alloc_(listpool* pool);
/// Free the block.
/// The block pointer is conveniently set to 0.
void listpool_free_(listpool* pool, void** block_ptr);
|