aboutsummaryrefslogtreecommitdiff
path: root/src/mempool.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mempool.h')
-rw-r--r--src/mempool.h75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/mempool.h b/src/mempool.h
new file mode 100644
index 0000000..6c25ac9
--- /dev/null
+++ b/src/mempool.h
@@ -0,0 +1,75 @@
+#ifndef MEMPOOL_H
+#define MEMPOOL_H
+
+#ifndef MEMPOOL_OBJ_TYPE
+#define MEMPOOL_OBJ_TYPE int
+#endif
+
+#ifndef MEMPOOL_CAP
+#define MEMPOOL_CAP (1 << 16)
+#endif
+
+#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) \
+ \
+ struct id##_block { \
+ union id##_chunk { \
+ MEMPOOL_OBJ_TYPE obj; \
+ union id##_chunk *next; \
+ } chunks[MEMPOOL_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 < MEMPOOL_CAP; i++) \
+ b->chunks[i].next = &b->chunks[i+1]; \
+ b->chunks[MEMPOOL_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