// vim:fileencoding=utf-8:foldmethod=marker

#ifndef PR_POOL_ALLOCATOR_H
#define PR_POOL_ALLOCATOR_H

#include "../../vendor/wapp/common/aliases/aliases.h"

#ifdef __cplusplus
extern "C" {
#endif

// ---------------------------------------------------------------------------
// Pool allocator — fixed-size slot allocator with self-managed growth
//
// Manages fixed-size slots arranged in contiguous blocks. The pool owns its
// memory (via wapp OS allocation) and grows on demand when the free list is empty.
//
// Usage:
//   PrPool pool;
//   prPoolInit(&pool, sizeof(Edge), 64);
//   Edge *e = prPoolAlloc(&pool);
//   prPoolFree(&pool, e);
//   prPoolDestroy(&pool);
// ---------------------------------------------------------------------------

typedef struct PrPool PrPool;

struct PrPool {
	void **blocks;      // array of allocated block pointers (for destroy)
	u64    block_count; // number of allocated blocks
	u64    block_cap;   // capacity of blocks array
	void  *free_list;   // intrusive free list head
	u64    slot_size;   // user-requested slot size
	u64    alloc_size;  // actual slot size used internally (>= slot_size, >= sizeof(void*))
	u64    block_slots; // slots per block
	u64    total;       // total slots ever allocated (diagnostics)
	u64    active;      // currently in use (diagnostics)
};

// Initialise a pool.
//   slot_size:     fixed size of each slot
//   initial_slots: starting capacity in slots (also used as block size)
void prPoolInit(PrPool *pool, u64 slot_size, u64 initial_slots);

// Allocate one slot. Grows by a new block if the free list is empty.
// Returns NULL only on allocation failure.
void *prPoolAlloc(PrPool *pool);

// Return a slot to the pool's free list. Safe no-op on NULL.
void prPoolFree(PrPool *pool, void *slot);

// Free all blocks and zero the pool.
void prPoolDestroy(PrPool *pool);

// Diagnostics
u64 prPoolTotalSlots(const PrPool *pool);
u64 prPoolActiveSlots(const PrPool *pool);

#ifdef __cplusplus
}
#endif

#endif // !PR_POOL_ALLOCATOR_H
