diff --git a/Juliet/include/Core/Container/Vector.h b/Juliet/include/Core/Container/Vector.h index a8bee89..679fd9d 100644 --- a/Juliet/include/Core/Container/Vector.h +++ b/Juliet/include/Core/Container/Vector.h @@ -6,7 +6,7 @@ namespace Juliet { - template + template struct VectorArena { void Create() @@ -16,8 +16,27 @@ namespace Juliet DataFirst = DataLast = nullptr; Count = 0; Stride = sizeof(Type); - Arena = ArenaAllocate(JULIET_DEBUG_ONLY({ .CanReserveMore = false })); + ArenaParams params{ .AllowRealloc = AllowRealloc JULIET_DEBUG_ONLY(, .CanReserveMore = false) }; + Arena = ArenaAllocate(params); + InternalArena = true; + + Reserve(ReserveSize); } + + void Create(NonNullPtr arena) + { + Assert(!Arena); + static_assert(AllowRealloc == false); + + DataFirst = DataLast = nullptr; + Count = 0; + Stride = sizeof(Type); + Arena = arena.Get(); + InternalArena = false; + + Reserve(ReserveSize); + } + void Destroy() { ArenaRelease(Arena); @@ -27,6 +46,22 @@ namespace Juliet Arena = nullptr; } + void Reserve(size_t newCapacity) + { + if (newCapacity > Capacity) + { + if (Data == nullptr) + { + Data = ArenaPushArray(Arena, newCapacity); + } + else if (AllowRealloc && InternalArena) + { + Data = static_cast(ArenaReallocate(Arena, Data, Capacity, newCapacity, AlignOf(Type), true)); + } + Capacity = newCapacity; + } + } + void Resize(size_t newCount) { Type* entry = ArenaPushArray(Arena, newCount); @@ -39,7 +74,7 @@ namespace Juliet { Assert(Arena); - Type* entry = ArenaPushStruct(Arena); + Type* entry = Data + (Count * Stride); *entry = value; if (Count == 0) @@ -54,7 +89,7 @@ namespace Juliet { Assert(Arena); - Type* entry = ArenaPushStruct(Arena); + Type* entry = Data + (Count * Stride); *entry = std::move(value); if (Count == 0) @@ -86,8 +121,6 @@ namespace Juliet { DataFirst = DataLast = nullptr; } - - ArenaPop(Arena, Stride); } void Clear() @@ -117,8 +150,11 @@ namespace Juliet Arena* Arena; Type* DataFirst; Type* DataLast; + Type* Data; size_t Count; + size_t Capacity; size_t Stride; + bool InternalArena : 1; }; static_assert(std::is_standard_layout_v>, "VectorArena must have a standard layout to remain POD-like."); diff --git a/Juliet/include/Juliet.h b/Juliet/include/Juliet.h index b202916..e200816 100644 --- a/Juliet/include/Juliet.h +++ b/Juliet/include/Juliet.h @@ -21,7 +21,7 @@ #ifdef DEBUG #define JULIET_DEBUG 1 -#define JULIET_DEBUG_ONLY(expr) expr +#define JULIET_DEBUG_ONLY(...) __VA_ARGS__ #else #define JULIET_DEBUG 0 #define JULIET_DEBUG_ONLY(expr) diff --git a/Juliet/src/Core/Memory/MemoryArena.cpp b/Juliet/src/Core/Memory/MemoryArena.cpp index 6b8eabe..50487aa 100644 --- a/Juliet/src/Core/Memory/MemoryArena.cpp +++ b/Juliet/src/Core/Memory/MemoryArena.cpp @@ -213,7 +213,9 @@ namespace Juliet void* ArenaReallocate(NonNullPtr arena, void* oldPtr, size_t oldSize, size_t newSize, size_t align, bool shouldBeZeroed) { - // Find the correct block + void* result = ArenaPush(arena, newSize, align, shouldBeZeroed); + + // Find the correct block to release Arena* block = nullptr; for (block = arena->Current; block != nullptr; block = block->Previous) { @@ -224,6 +226,10 @@ namespace Juliet } Assert(block != nullptr); + // Copy old to new + MemCopy(result, oldPtr, oldSize); + + // Zero the old memory MemoryZero(oldPtr, oldSize); ArenaFreeNode* freeNode = static_cast(oldPtr); ptrdiff_t posPtr = static_cast(oldPtr) - reinterpret_cast(block); @@ -244,7 +250,7 @@ namespace Juliet } block->FreeNodes = freeNode; } - return ArenaPush(arena, newSize, align, shouldBeZeroed); + return result; } void ArenaPopTo(NonNullPtr arena, size_t position) diff --git a/Juliet/src/Core/Memory/MemoryArenaTests.cpp b/Juliet/src/Core/Memory/MemoryArenaTests.cpp index 015961f..b25563c 100644 --- a/Juliet/src/Core/Memory/MemoryArenaTests.cpp +++ b/Juliet/src/Core/Memory/MemoryArenaTests.cpp @@ -117,28 +117,6 @@ namespace Juliet::UnitTest ArenaRelease(testArena); - // Setup Pool and Arena for Pop Tests - size_t testPoolSize = Megabytes(1); - void* testBacking = Calloc(1, testPoolSize); - MemoryPool pool; - pool.BaseAddress = testBacking; - pool.TotalSize = testPoolSize; - pool.FreeList = nullptr; - - // Initialize FreeList (Simulate pool) - size_t blockSize = Kilobytes(128); - size_t numBlocks = testPoolSize / blockSize; - uint8* ptr = static_cast(testBacking); - for (size_t i = 0; i < numBlocks; ++i) - { - MemoryBlock* blk = reinterpret_cast(ptr + i * blockSize); - blk->Magic = MemoryBlock::kMagic; - blk->TotalSize = blockSize; - blk->Used = 0; - blk->Next = pool.FreeList; - pool.FreeList = blk; - } - { // Test reallocate Arena* arena = ArenaAllocate({ .AllowRealloc = true }); @@ -154,6 +132,8 @@ namespace Juliet::UnitTest Assert(secondCharArray); Assert(thirdCharArray); Assert(fourthCharArray); + + ArenaRelease(arena); } printf("All Paged MemoryArena tests passed.\n");