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  | 
