#include "object_pool.h" #include "../memory/memory.h" typedef struct BzObjectPool { void *objects; size_t stride; size_t numObjects; i32 firstFree; } BzObjectPool; BzObjectPool *bzObjectPoolCreate(const BzObjectPoolDesc *desc) { BZ_ASSERT(desc->objectSize > 0); // NOTE: Since object bits are used as a free list // when not in use, we must ensure they can hold i32. size_t stride = desc->objectSize; if (stride < sizeof(i32)) { stride = sizeof(i32); } size_t numBytes = sizeof(BzObjectPool) + desc->numObjects * stride; BzObjectPool *pool = bzAlloc(numBytes); *pool = (BzObjectPool) { .objects=pool + 1, .stride=stride, .numObjects=desc->numObjects, .firstFree=0, }; // Link free list for (size_t i = 0; i < pool->numObjects - 1; i++) { i32 *object = bzObjectPoolGetObject(pool, i); *object = (i32) (i + 1); } i32 *lastObject = bzObjectPoolGetObject(pool, pool->numObjects - 1); *lastObject = -1; return pool; } void bzObjectPoolDestroy(BzObjectPool *pool) { bzFree(pool); } size_t bzObjectPoolCalcNumFree(BzObjectPool *pool) { size_t count = 0; i32 idx = pool->firstFree; while (idx != -1) { count++; i32 *object = bzObjectPoolGetObject(pool, idx); idx = *object; } return count; } void *bzObjectPool(BzObjectPool *pool) { if (pool->firstFree == -1) return NULL; i32 *object = bzObjectPoolGetObject(pool, pool->firstFree); pool->firstFree = *object; return object; } void *bzObjectPoolGetObject(BzObjectPool *pool, i32 idx) { BZ_ASSERT(idx >= 0 && (size_t) idx < pool->numObjects); return (void *) ((u8 *) pool->objects + idx * pool->stride); } i32 bzObjectPoolGetIdx(BzObjectPool *pool, void *object) { size_t objectIdx = (size_t) object - (size_t) pool->objects; return (i32) (objectIdx / pool->stride); } void bzObjectPoolRelease(BzObjectPool *pool, void *object) { size_t objectIdx = bzObjectPoolGetIdx(pool, object); BZ_ASSERT(objectIdx < pool->numObjects); *(i32 *) ((u8 *) pool->objects + objectIdx * pool->stride) = pool->firstFree; pool->firstFree = (i32) objectIdx; }