File syn_pool.h¶
File List > src > syntropic > util > syn_pool.h
Go to the documentation of this file
#ifndef SYN_POOL_H
#define SYN_POOL_H
#if __has_include("syn_config.h")
#include "syn_config.h"
#endif
#if !defined(SYN_USE_POOL) || SYN_USE_POOL
#include "../util/syn_assert.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ── Helpers ────────────────────────────────────────────────────────────── */
#define SYN_POOL_ALIGN4(x) (((x) + 3u) & ~3u)
#define SYN_POOL_BUF_SIZE(block_size, count) (SYN_POOL_ALIGN4(block_size) * (count))
/* ── Pool struct ────────────────────────────────────────────────────────── */
typedef struct {
void *freelist;
uint8_t *buf;
size_t block_size;
size_t block_count;
size_t used;
size_t high_water;
} SYN_Pool;
/* ── API ────────────────────────────────────────────────────────────────── */
static inline void syn_pool_init(SYN_Pool *pool, void *buf, size_t buf_size, size_t block_size)
{
SYN_ASSERT(pool != NULL);
SYN_ASSERT(buf != NULL);
/* Enforce minimum block size (must hold a pointer for the freelist) */
if (block_size < sizeof(void *)) {
block_size = sizeof(void *);
}
/* Round up to 4-byte alignment */
block_size = SYN_POOL_ALIGN4(block_size);
size_t count = buf_size / block_size;
SYN_ASSERT(count > 0);
pool->buf = (uint8_t *)buf;
pool->block_size = block_size;
pool->block_count = count;
pool->used = 0;
pool->high_water = 0;
/* Thread freelist through all blocks */
pool->freelist = NULL;
size_t i = count;
while (i > 0) {
i--;
uint8_t *blk = pool->buf + i * block_size;
void *next = pool->freelist;
memcpy(blk, &next, sizeof(void *));
pool->freelist = (void *)blk;
}
}
static inline void *syn_pool_alloc(SYN_Pool *pool)
{
SYN_ASSERT(pool != NULL);
if (pool->freelist == NULL) {
return NULL; /* exhausted */
}
/* Pop head of freelist */
void *blk = pool->freelist;
void *next = NULL;
memcpy(&next, blk, sizeof(void *));
pool->freelist = next;
pool->used++;
if (pool->used > pool->high_water) {
pool->high_water = pool->used;
}
return blk;
}
static inline void syn_pool_free(SYN_Pool *pool, void *block)
{
SYN_ASSERT(pool != NULL);
if (block == NULL)
return;
/* Push onto freelist head */
void *next = pool->freelist;
memcpy(block, &next, sizeof(void *));
pool->freelist = block;
SYN_ASSERT(pool->used > 0);
pool->used--;
}
static inline size_t syn_pool_available(const SYN_Pool *pool)
{
SYN_ASSERT(pool != NULL);
return pool->block_count - pool->used;
}
static inline size_t syn_pool_used(const SYN_Pool *pool)
{
SYN_ASSERT(pool != NULL);
return pool->used;
}
static inline size_t syn_pool_high_watermark(const SYN_Pool *pool)
{
SYN_ASSERT(pool != NULL);
return pool->high_water;
}
static inline size_t syn_pool_block_size(const SYN_Pool *pool)
{
SYN_ASSERT(pool != NULL);
return pool->block_size;
}
static inline size_t syn_pool_block_count(const SYN_Pool *pool)
{
SYN_ASSERT(pool != NULL);
return pool->block_count;
}
#ifdef __cplusplus
}
#endif
#endif /* SYN_USE_POOL */
#endif /* SYN_POOL_H */