blob: 7d065f558ed098182551025d8dfdeedc5eb89dec (
plain)
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
|
#ifndef MEMPOOL_H
#define MEMPOOL_H
/* To generate use MEMPOOL_GENERATE(id, type, cap), where functions
* _mempool_allocate() and _mempool_free(type *obj) will be prefixed with id
* and can be used to allocate objects of type <type> with <cap> objects in
* each block
*/
#define for_each_block(id, b, head) \
for(struct id##_block *b = (head), *next = NULL; \
b && (next = b->next, 1); b = next)
#define get_last_block(b) \
while((b)->next != NULL) (b) = (b)->next
#define MEMPOOL_GENERATE(id, type, cap) \
\
struct id##_block { \
union id##_chunk { \
type obj; \
union id##_chunk *next; \
} chunks[cap]; \
\
struct id##_block *next; \
}; \
\
static union id##_chunk *id##_ap = NULL; \
static struct id##_block id##_block; \
static size_t id##_allocations = 0; \
\
static inline void *_##id##_mempool_init_block(struct id##_block *b) \
{ \
b->next = NULL; \
for(size_t i = 0; i < cap; i++) \
b->chunks[i].next = &b->chunks[i+1]; \
b->chunks[cap-1].next = NULL; \
\
return b->chunks; \
} \
\
static inline void *id##_mempool_allocate(void) \
{ \
if(!id##_ap) { \
struct id##_block *new_block = &(id##_block); \
if((id##_allocations) > 0) { \
new_block = malloc(sizeof(*new_block)); \
struct id##_block *last_block = &(id##_block); \
get_last_block(last_block); \
last_block->next = new_block; \
} \
id##_ap = _##id##_mempool_init_block(new_block); \
} \
\
id##_allocations++; \
\
void *ptr = &(id##_ap)->obj; \
id##_ap = (id##_ap)->next; \
return ptr; \
} \
\
static inline void id##_mempool_free(void *ptr) \
{ \
((union id##_chunk *)ptr)->next = id##_ap; \
id##_ap = (union id##_chunk *)ptr; \
\
if(--id##_allocations == 0) { \
for_each_block(id, b, (id##_block).next) \
free(b); \
id##_ap = id##_block.chunks; \
} \
} \
#endif
|