This is an allocator that is used in replace of malloc if you do a lot of rapid, but small allocations on the heap. I wrote this for reducing system calls to improve performance. It works, but I've never written an allocator before, so I wondered if there is any improvements I can make generally with regards to readability, edge cases, or the concept in general.
pool.h
#ifndef POOL_H
#define POOL_H
#include <stdint.h>
struct list;
struct block {
void* data;
uint64_t len;
};
struct data_pool {
struct list* blocks;
struct block* current;
uint64_t page_size;
};
struct data_pool
make_pool(uint64_t capacity);
void*
alloc(struct data_pool* pool, size_t len);
void
destroy_pool(struct data_pool* pool);
#endif
pool.c
#include <stdlib.h>
#include "pool.h"
#include "list.h"
#include <assert.h>
struct data_pool
make_pool(uint64_t page_size) {
struct data_pool pool;
pool.blocks = make_list(4);
pool.page_size = page_size;
return pool;
}
void
push_block(struct data_pool* pool) {
struct block* b = malloc(sizeof(*b));
assert(b != NULL);
b->data = malloc(sizeof(*b->data) * pool->page_size);
assert(b->data != NULL);
b->len = 0;
push_item(pool->blocks, b);
pool->current = b;
}
void*
alloc(struct data_pool* pool, size_t len) {
if (pool->current->len + len >= pool->page_size) {
push_block(pool);
}
pool->current->len += len;
return &pool->current->data[pool->current->len];
}
void
destroy_pool(struct data_pool* pool) {
for (uint64_t i = 0; i < pool->blocks->index; i++) {
struct block* block = pool->blocks->items[i];
free(block->data);
free(block);
}
}