aboutsummaryrefslogtreecommitdiff
path: root/listpool/src/listpool.c
diff options
context:
space:
mode:
Diffstat (limited to 'listpool/src/listpool.c')
-rw-r--r--listpool/src/listpool.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/listpool/src/listpool.c b/listpool/src/listpool.c
new file mode 100644
index 0000000..9c86a3b
--- /dev/null
+++ b/listpool/src/listpool.c
@@ -0,0 +1,78 @@
1#include "listpool.h"
2
3#include <string.h>
4
5void listpool_make_(listpool* pool, list* nodes, void* blocks,
6 size_t num_blocks, size_t block_size_bytes) {
7 assert(pool);
8 pool->block_size_bytes = block_size_bytes;
9 pool->num_blocks = num_blocks;
10 pool->free = &nodes[0];
11 pool->used = 0;
12 pool->nodes = nodes;
13 pool->blocks = blocks;
14 list_make(nodes, num_blocks);
15 memset(blocks, 0, num_blocks * block_size_bytes);
16}
17
18void* listpool_alloc_(listpool* pool) {
19 assert(pool);
20 if (!pool->free) {
21 return 0;
22 }
23
24 const size_t index = pool->free - pool->nodes;
25 assert(index < pool->num_blocks);
26
27 list* free = pool->free;
28 pool->free = pool->free->next;
29
30 // pool->used is always the head of the used list, so prepend the new item to
31 // the list.
32 list* new_used = free;
33 new_used->prev = 0;
34 new_used->next = pool->used;
35 if (pool->used) {
36 pool->used->prev = new_used;
37 }
38 pool->used = new_used;
39
40 return pool->blocks + index * pool->block_size_bytes;
41}
42
43void listpool_free_(listpool* pool, void** block_ptr) {
44 assert(pool);
45 assert(block_ptr);
46
47 memset(*block_ptr, 0, pool->block_size_bytes);
48
49 const size_t index =
50 ((uint8_t*)*block_ptr - pool->blocks) / pool->block_size_bytes;
51 assert(index < pool->num_blocks);
52
53 list* item = &pool->nodes[index];
54
55 // We must remove the item from the used list first.
56 if (item->prev) {
57 item->prev->next = item->next;
58 }
59 if (item->next) {
60 item->next->prev = item->prev;
61 }
62 if (item == pool->used) {
63 pool->used = item->next;
64 }
65
66 // pool->free is always the head of the free list, so prepend the new item to
67 // the list. The item is now free to wire after removing it from the used
68 // list.
69 if (!pool->free) {
70 pool->free = item;
71 } else {
72 item->next = pool->free;
73 pool->free->prev = item;
74 pool->free = item;
75 }
76
77 *block_ptr = 0;
78}