diff options
Diffstat (limited to 'src/mempool.h')
-rw-r--r-- | src/mempool.h | 75 |
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 |