1 2 3 4 5 6 7 8 9 10 11 | struct SlicedArray { MemArena arena; uptr *slices[128]; /* this can be dynamic too */ sizet sliceCount; sizet itemCount; sizet effectiveItemSize; sizet itemsPerSlice; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | INLINE void initSlicedArray(SlicedArray *array, sizet sliceSize, sizet itemSize, u32 alignment) { array->effectiveItemSize = ALIGN_POW_2(itemSize, alignment); /* ensure that at least one item fits */ ASSERT(sliceSize >= (array->effectiveItemSize + sizeof(MemBlockFooter))); sizet effectiveSliceSize = sliceSize - sizeof(MemBlockFooter); array->itemsPerSlice = (effectiveSliceSize / array->effectiveItemSize); sizet arenaBlockSize = sliceSize; initArena(&array->arena, win32Allocate, win32Deallocate, arenaBlockSize); array->sliceCount = 0; array->itemCount = 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 | INLINE void *pushItem(SlicedArray *array) { sizet prevSliceCount = array->sliceCount; void *result = pushSize(&array->arena, array->effectiveItemSize, noAlignNoClear()); ++array->itemCount; array->sliceCount = array->arena.blockCount; if (prevSliceCount != array->sliceCount) { array->slices[array->sliceCount - 1] = (uptr *)array->arena.base; } return result; } |
1 2 3 4 5 6 7 8 | INLINE void *getItem(SlicedArray *array, sizet index) { sizet sliceIndex = (index / array->itemsPerSlice); sizet itemIndex = (index % array->itemsPerSlice); void *slice = array->slices[sliceIndex]; void *result = (u8 *)slice + (itemIndex * array->effectiveItemSize); return result; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | struct Item; /* some data type */ SlicedArray array; initSlicedArray(&array, MEGABYTES(1), sizeof(Item), 4); Item *item = pushItem(&array); /* adding */ Item *firstItem = getItem(&array, 0); /* fetching */ /* iteration */ sizet itemIndex; for (itemIndex = 0; itemIndex < array.itemCount; ++itemIndex) { Item *item = getItem(&array, itemIndex); } |