diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 17604dd..efcf75d 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -37,6 +37,7 @@ set(BreezeSources breeze/utils/array.c breeze/utils/heap.c + breeze/utils/object_pool.c breeze/utils/tokenizer.c ) @@ -51,6 +52,7 @@ set(BreezeHeaders breeze/utils/array.h breeze/utils/heap.h + breeze/utils/object_pool.h breeze/utils/string.h breeze/utils/tokenizer.h diff --git a/engine/breeze/utils/object_pool.c b/engine/breeze/utils/object_pool.c new file mode 100644 index 0000000..1ffbfeb --- /dev/null +++ b/engine/breeze/utils/object_pool.c @@ -0,0 +1,61 @@ +#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; +} diff --git a/engine/breeze/utils/object_pool.h b/engine/breeze/utils/object_pool.h new file mode 100644 index 0000000..5650dcd --- /dev/null +++ b/engine/breeze/utils/object_pool.h @@ -0,0 +1,19 @@ +#ifndef BREEZE_OBJECT_POOL_H +#define BREEZE_OBJECT_POOL_H + +#include "../defines.h" + +typedef struct BzObjectPool BzObjectPool; + +typedef struct BzObjectPoolDesc { + size_t objectSize; + size_t numObjects; +} BzObjectPoolDesc; + +BzObjectPool *bzObjectPoolCreate(const BzObjectPoolDesc *desc); +void bzObjectPoolDestroy(BzObjectPool *pool); + +void *bzObjectPool(BzObjectPool *pool); +void bzObjectPoolRelease(BzObjectPool *pool, void *object); + +#endif //BREEZE_OBJECT_POOL_H