Add page support to object pool
This commit is contained in:
@@ -2,13 +2,65 @@
|
||||
|
||||
#include "../memory/memory.h"
|
||||
|
||||
typedef union BzObjectIdx {
|
||||
struct {
|
||||
u16 idx;
|
||||
u16 page;
|
||||
};
|
||||
u32 value;
|
||||
} BzObjectIdx;
|
||||
|
||||
#define INVALID_OBJECT_IDX (UINT32_MAX)
|
||||
|
||||
static_assert(sizeof(BzObjectIdx) == 4, "");
|
||||
|
||||
typedef struct BzObjectPool {
|
||||
void *objects;
|
||||
void **pages;
|
||||
size_t pageCapacity;
|
||||
size_t pageSize;
|
||||
size_t objectsPerPage;
|
||||
size_t stride;
|
||||
size_t numObjects;
|
||||
i32 firstFree;
|
||||
|
||||
size_t numFree;
|
||||
BzObjectIdx firstFree;
|
||||
|
||||
BzObjectPoolFunc constructor;
|
||||
BzObjectPoolFunc destructor;
|
||||
} BzObjectPool;
|
||||
|
||||
static void initializePage(BzObjectPool *pool, u16 pageIdx) {
|
||||
BZ_ASSERT(pageIdx < UINT8_MAX);
|
||||
// Link free list
|
||||
for (size_t i = 0; i < pool->objectsPerPage - 1; i++) {
|
||||
BzObjectIdx idx = {.page = pageIdx, .idx = i};
|
||||
BzObjectIdx *obj = bzObjectPoolGetObject(pool, idx.value);
|
||||
|
||||
BzObjectIdx nextIdx = {.page = pageIdx, .idx = i + 1};
|
||||
obj->value = nextIdx.value;
|
||||
}
|
||||
BzObjectIdx lastIdx = {.page = pageIdx, .idx = pool->objectsPerPage - 1};
|
||||
BzObjectIdx *lastObj = bzObjectPoolGetObject(pool, lastIdx.value);
|
||||
lastObj->value = pool->firstFree.value;
|
||||
pool->firstFree = (BzObjectIdx) {.page = pageIdx, .idx = 0};
|
||||
|
||||
pool->numFree += pool->objectsPerPage;
|
||||
}
|
||||
static void addNewPage(BzObjectPool *pool) {
|
||||
if (pool->pageSize >= pool->pageCapacity) {
|
||||
size_t newCapacity = pool->pageCapacity << 1;
|
||||
void **newPages = bzResize(pool->pages, sizeof(*newPages) * newCapacity);
|
||||
BZ_ASSERT(newPages);
|
||||
pool->pages = newPages;
|
||||
pool->pageCapacity = newCapacity;
|
||||
}
|
||||
void *newPage = bzAlloc(pool->stride * pool->objectsPerPage);
|
||||
BZ_ASSERT(newPage);
|
||||
size_t pageIdx = pool->pageSize;
|
||||
pool->pages[pageIdx] = newPage;
|
||||
pool->pageSize++;
|
||||
initializePage(pool, pageIdx);
|
||||
}
|
||||
|
||||
BzObjectPool *bzObjectPoolCreate(const BzObjectPoolDesc *desc) {
|
||||
BZ_ASSERT(desc->objectSize > 0);
|
||||
|
||||
@@ -18,58 +70,83 @@ BzObjectPool *bzObjectPoolCreate(const BzObjectPoolDesc *desc) {
|
||||
if (stride < sizeof(i32)) {
|
||||
stride = sizeof(i32);
|
||||
}
|
||||
BZ_ASSERT(desc->objectsPerPage > 0);
|
||||
BZ_ASSERT(desc->objectsPerPage < (2 << 23));
|
||||
|
||||
size_t numBytes = sizeof(BzObjectPool) + desc->numObjects * stride;
|
||||
BzObjectPool *pool = bzAlloc(numBytes);
|
||||
size_t objectsPerPage = desc->objectsPerPage;
|
||||
|
||||
void *firstPage = bzAlloc(stride * objectsPerPage);
|
||||
BZ_ASSERT(firstPage);
|
||||
|
||||
size_t pageCapacity = 8;
|
||||
void **pages = bzAlloc(sizeof(*pages) * pageCapacity);
|
||||
BZ_ASSERT(pages);
|
||||
pages[0] = firstPage;
|
||||
|
||||
BzObjectPool *pool = bzAlloc(sizeof(*pool));
|
||||
*pool = (BzObjectPool) {
|
||||
.objects=pool + 1,
|
||||
.stride=stride,
|
||||
.numObjects=desc->numObjects,
|
||||
.firstFree=0,
|
||||
.pages = pages,
|
||||
.pageSize = 0,
|
||||
.pageCapacity = pageCapacity,
|
||||
.objectsPerPage = objectsPerPage,
|
||||
.stride = stride,
|
||||
};
|
||||
pool->firstFree.value = INVALID_OBJECT_IDX;
|
||||
|
||||
// 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;
|
||||
|
||||
addNewPage(pool);
|
||||
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;
|
||||
size_t bzObjectPoolGetNumFree(BzObjectPool *pool) {
|
||||
return pool->numFree;
|
||||
}
|
||||
void *bzObjectPool(BzObjectPool *pool) {
|
||||
if (pool->firstFree == -1)
|
||||
return NULL;
|
||||
i32 *object = bzObjectPoolGetObject(pool, pool->firstFree);
|
||||
pool->firstFree = *object;
|
||||
if (pool->firstFree.value == INVALID_OBJECT_IDX) {
|
||||
addNewPage(pool);
|
||||
BZ_ASSERT(pool->firstFree.value != INVALID_OBJECT_IDX);
|
||||
}
|
||||
BzObjectIdx *object = (BzObjectIdx *) bzObjectPoolGetObject(pool, pool->firstFree.value);
|
||||
pool->firstFree = *object;
|
||||
|
||||
BZ_ASSERT(pool->numFree > 0);
|
||||
pool->numFree--;
|
||||
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);
|
||||
void *bzObjectPoolGetObject(BzObjectPool *pool, u32 idx) {
|
||||
BzObjectIdx objectIdx = {.value = idx};
|
||||
BZ_ASSERT(objectIdx.page >= 0 && objectIdx.page < pool->pageSize);
|
||||
BZ_ASSERT(objectIdx.idx >= 0 && objectIdx.idx < pool->objectsPerPage);
|
||||
|
||||
void *page = pool->pages[objectIdx.page];
|
||||
return (void *) ((u8 *) page + objectIdx.idx * pool->stride);
|
||||
}
|
||||
i32 bzObjectPoolGetIdx(BzObjectPool *pool, void *object) {
|
||||
size_t objectIdx = (size_t) object - (size_t) pool->objects;
|
||||
return (i32) (objectIdx / pool->stride);
|
||||
u32 bzObjectPoolGetIdx(BzObjectPool *pool, void *object) {
|
||||
u16 pageIdx = pool->pageSize;
|
||||
u16 idx = 0;
|
||||
|
||||
for (size_t i = 0; i < pool->pageSize; i++) {
|
||||
void *start = pool->pages[i];
|
||||
void *end = (u8 *) start + pool->objectsPerPage * pool->stride;
|
||||
|
||||
if (object >= start && object < end) {
|
||||
pageIdx = i;
|
||||
idx = (size_t) object - (size_t) start;
|
||||
idx = idx / pool->stride;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BZ_ASSERT(pageIdx < pool->pageSize);
|
||||
BzObjectIdx objectIdx = {.page = pageIdx, .idx = idx};
|
||||
return objectIdx.value;
|
||||
}
|
||||
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;
|
||||
BzObjectIdx objectIdx = {.value = bzObjectPoolGetIdx(pool, object)};
|
||||
|
||||
void *page = pool->pages[objectIdx.page];
|
||||
*(BzObjectIdx *) ((u8 *) page + objectIdx.idx * pool->stride) = pool->firstFree;
|
||||
pool->firstFree = objectIdx;
|
||||
pool->numFree++;
|
||||
}
|
||||
|
||||
@@ -5,18 +5,22 @@
|
||||
|
||||
typedef struct BzObjectPool BzObjectPool;
|
||||
|
||||
typedef void (*BzObjectPoolFunc)(void *object);
|
||||
|
||||
typedef struct BzObjectPoolDesc {
|
||||
size_t objectSize;
|
||||
size_t numObjects;
|
||||
size_t objectsPerPage;
|
||||
BzObjectPoolFunc constructor;
|
||||
BzObjectPoolFunc destructor;
|
||||
} BzObjectPoolDesc;
|
||||
|
||||
BzObjectPool *bzObjectPoolCreate(const BzObjectPoolDesc *desc);
|
||||
void bzObjectPoolDestroy(BzObjectPool *pool);
|
||||
|
||||
size_t bzObjectPoolCalcNumFree(BzObjectPool *pool);
|
||||
size_t bzObjectPoolGetNumFree(BzObjectPool *pool);
|
||||
void *bzObjectPool(BzObjectPool *pool);
|
||||
void *bzObjectPoolGetObject(BzObjectPool *pool, i32 idx);
|
||||
i32 bzObjectPoolGetIdx(BzObjectPool *pool, void *object);
|
||||
void *bzObjectPoolGetObject(BzObjectPool *pool, u32 idx);
|
||||
u32 bzObjectPoolGetIdx(BzObjectPool *pool, void *object);
|
||||
void bzObjectPoolRelease(BzObjectPool *pool, void *object);
|
||||
|
||||
#endif //BREEZE_OBJECT_POOL_H
|
||||
|
||||
@@ -42,7 +42,7 @@ BzSpatialGrid *bzSpatialGridCreate(const BzSpatialGridDesc *desc) {
|
||||
}
|
||||
grid->entriesPool = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
||||
.objectSize=sizeof(BzSpatialGridEntry) + desc->userDataSize,
|
||||
.numObjects=1024,
|
||||
.objectsPerPage=1024,
|
||||
});
|
||||
return grid;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ bool init(void *userData) {
|
||||
// init pools
|
||||
game->pools.pathData = bzObjectPoolCreate(&(BzObjectPoolDesc) {
|
||||
.objectSize=sizeof(PathData),
|
||||
.numObjects=512
|
||||
.objectsPerPage=512
|
||||
});
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ void imguiRender(float dt, void *userData) {
|
||||
createWorker((Position) {1100, 400}, (Size) {10, 10}, game->entityGrid,
|
||||
&game->map.tilesets[2], 1322);
|
||||
}
|
||||
igText("Num paths from pool available: %llu", bzObjectPoolCalcNumFree(game->pools.pathData));
|
||||
igText("Num paths from pool available: %llu", bzObjectPoolGetNumFree(game->pools.pathData));
|
||||
const char *inputState = "NONE";
|
||||
switch (input->state) {
|
||||
case INPUT_NONE:
|
||||
|
||||
@@ -107,7 +107,7 @@ bool initTreesLayer(BzTileMap *map, BzTileLayer *layer) {
|
||||
f32 posX = layer->offsetX + x * sizeX;
|
||||
f32 posY = layer->offsetY + y * sizeY;
|
||||
ecs_entity_t e = ecs_new_id(ECS);
|
||||
//bzSpatialGridInsert(game->entityGrid, &e, posX, posY, sizeX, sizeY);;
|
||||
bzSpatialGridInsert(game->entityGrid, &e, posX, posY, sizeX, sizeY);
|
||||
posX += sizeX * 0.5f;
|
||||
posY += sizeY * 0.5f;
|
||||
ecs_add(ECS, e, TextureTerrain);
|
||||
|
||||
Reference in New Issue
Block a user