Files
PixelDefense/engine/breeze/utils/object_pool.c
2023-11-15 20:15:59 +01:00

62 lines
1.7 KiB
C

#include "object_pool.h"
#include "../core/memory.h"
typedef struct BzObjectPool {
void *objects;
size_t stride;
size_t numObjects;
i32 firstFree;
} BzObjectPool;
static i32 *bzObjectPoolGetObject(const BzObjectPool *pool, size_t idx) {
return (i32 *) ((u8 *) pool->objects + idx * pool->stride);
}
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);
}
void *bzObjectPool(BzObjectPool *pool) {
if (pool->firstFree == -1)
return NULL;
i32 *object = bzObjectPoolGetObject(pool, pool->firstFree);
pool->firstFree = *object;
return object;
}
void bzObjectPoolRelease(BzObjectPool *pool, void *object) {
size_t objectIdx = (size_t) object - (size_t)pool->objects;
BZ_ASSERT(objectIdx < pool->numObjects);
*(i32 *) objectIdx = pool->firstFree;
pool->firstFree = (i32) objectIdx;
}