Mainly for practicing purposes, I'm trying to implement a simple, yet efficient memory pool. It's basically a linked list that is able to grow, with fixed sized members. Each node has a flag if it's free or not. I'm not sure if I'm doing it the right way, and especially confused about how to deal with alignment, and thread safety. I know the basic concept, just don't know how to implement in this case. Could you please help me how to improve my code? This is what I have now:
#include <stdbool.h>
#include "mem_pool.h"
typedef struct block Block;
typedef struct block
{
Block *next;
void *ptr;
bool free;
} Block;
struct mem_pool
{
Block *head;
void *memory;
size_t memory_size;
size_t memb_size;
};
#define get_ptr_and_increase(pool, size) pool->memory; pool->memory += size
#define add_block_size(pool) pool->memory_size += sizeof(Block) + pool->memb_size
static Block *new_block(MemoryPool *pool, bool is_free)
{
Block *block = get_ptr_and_increase(pool, sizeof(Block));
block->ptr = get_ptr_and_increase(pool, pool->memb_size);
block->next = NULL;
block->free = is_free;
return block;
}
MemoryPool *pool_init(size_t memb_size)
{
MemoryPool *pool = malloc(sizeof(MemoryPool));
pool->memb_size = memb_size;
pool->memory_size = 0;
add_block_size(pool);
pool->memory = malloc(pool->memory_size);
pool->head = new_block(pool, true);
return pool;
}
static Block *find_free(MemoryPool *pool)
{
Block *current = pool->head;
while (NULL != current && false == current->free) {
current = current->next;
}
return current;
}
static void add_new_head(MemoryPool *pool)
{
Block *tmp = pool->head;
pool->head = new_block(pool, false);
pool->head->next = tmp;
add_block_size(pool);
pool->memory = realloc(pool->memory, pool->memory_size);
}
void *pool_alloc(MemoryPool *pool)
{
Block *free = find_free(pool);
if (NULL != free) {
return free->ptr;
}
add_new_head(pool);
return pool->head->ptr;
}
void pool_free(MemoryPool *pool, void *block)
{
Block *current = pool->head;
while (current->ptr != block) {
current = current->next;
}
current->free = true;
}
void pool_destroy(MemoryPool *pool)
{
free(pool->memory - pool->memory_size);
free(pool);
}