Reallocate-Arena #1

Merged
Patedam merged 7 commits from Reallocate-Arena into main 2026-02-14 11:24:30 -05:00
4 changed files with 53 additions and 31 deletions
Showing only changes of commit 536f6c5c60 - Show all commits

View File

@@ -6,7 +6,7 @@
namespace Juliet
{
template <typename Type>
template <typename Type, size_t ReserveSize = 16, bool AllowRealloc = false>
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> 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<Type>(Arena, newCapacity);
}
else if (AllowRealloc && InternalArena)
{
Data = static_cast<Type*>(ArenaReallocate(Arena, Data, Capacity, newCapacity, AlignOf(Type), true));
}
Capacity = newCapacity;
}
}
void Resize(size_t newCount)
{
Type* entry = ArenaPushArray<Type>(Arena, newCount);
@@ -39,7 +74,7 @@ namespace Juliet
{
Assert(Arena);
Type* entry = ArenaPushStruct<Type>(Arena);
Type* entry = Data + (Count * Stride);
*entry = value;
if (Count == 0)
@@ -54,7 +89,7 @@ namespace Juliet
{
Assert(Arena);
Type* entry = ArenaPushStruct<Type>(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<int>>,
"VectorArena must have a standard layout to remain POD-like.");

View File

@@ -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)

View File

@@ -213,7 +213,9 @@ namespace Juliet
void* ArenaReallocate(NonNullPtr<Arena> 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<ArenaFreeNode*>(oldPtr);
ptrdiff_t posPtr = static_cast<Byte*>(oldPtr) - reinterpret_cast<Byte*>(block);
@@ -244,7 +250,7 @@ namespace Juliet
}
block->FreeNodes = freeNode;
}
return ArenaPush(arena, newSize, align, shouldBeZeroed);
return result;
}
void ArenaPopTo(NonNullPtr<Arena> arena, size_t position)

View File

@@ -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<uint8*>(testBacking);
for (size_t i = 0; i < numBlocks; ++i)
{
MemoryBlock* blk = reinterpret_cast<MemoryBlock*>(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");