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 namespace Juliet
{ {
template <typename Type> template <typename Type, size_t ReserveSize = 16, bool AllowRealloc = false>
struct VectorArena struct VectorArena
{ {
void Create() void Create()
@@ -16,8 +16,27 @@ namespace Juliet
DataFirst = DataLast = nullptr; DataFirst = DataLast = nullptr;
Count = 0; Count = 0;
Stride = sizeof(Type); 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() void Destroy()
{ {
ArenaRelease(Arena); ArenaRelease(Arena);
@@ -27,6 +46,22 @@ namespace Juliet
Arena = nullptr; 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) void Resize(size_t newCount)
{ {
Type* entry = ArenaPushArray<Type>(Arena, newCount); Type* entry = ArenaPushArray<Type>(Arena, newCount);
@@ -39,7 +74,7 @@ namespace Juliet
{ {
Assert(Arena); Assert(Arena);
Type* entry = ArenaPushStruct<Type>(Arena); Type* entry = Data + (Count * Stride);
*entry = value; *entry = value;
if (Count == 0) if (Count == 0)
@@ -54,7 +89,7 @@ namespace Juliet
{ {
Assert(Arena); Assert(Arena);
Type* entry = ArenaPushStruct<Type>(Arena); Type* entry = Data + (Count * Stride);
*entry = std::move(value); *entry = std::move(value);
if (Count == 0) if (Count == 0)
@@ -86,8 +121,6 @@ namespace Juliet
{ {
DataFirst = DataLast = nullptr; DataFirst = DataLast = nullptr;
} }
ArenaPop(Arena, Stride);
} }
void Clear() void Clear()
@@ -117,8 +150,11 @@ namespace Juliet
Arena* Arena; Arena* Arena;
Type* DataFirst; Type* DataFirst;
Type* DataLast; Type* DataLast;
Type* Data;
size_t Count; size_t Count;
size_t Capacity;
size_t Stride; size_t Stride;
bool InternalArena : 1;
}; };
static_assert(std::is_standard_layout_v<VectorArena<int>>, static_assert(std::is_standard_layout_v<VectorArena<int>>,
"VectorArena must have a standard layout to remain POD-like."); "VectorArena must have a standard layout to remain POD-like.");

View File

@@ -21,7 +21,7 @@
#ifdef DEBUG #ifdef DEBUG
#define JULIET_DEBUG 1 #define JULIET_DEBUG 1
#define JULIET_DEBUG_ONLY(expr) expr #define JULIET_DEBUG_ONLY(...) __VA_ARGS__
#else #else
#define JULIET_DEBUG 0 #define JULIET_DEBUG 0
#define JULIET_DEBUG_ONLY(expr) #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) 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; Arena* block = nullptr;
for (block = arena->Current; block != nullptr; block = block->Previous) for (block = arena->Current; block != nullptr; block = block->Previous)
{ {
@@ -224,6 +226,10 @@ namespace Juliet
} }
Assert(block != nullptr); Assert(block != nullptr);
// Copy old to new
MemCopy(result, oldPtr, oldSize);
// Zero the old memory
MemoryZero(oldPtr, oldSize); MemoryZero(oldPtr, oldSize);
ArenaFreeNode* freeNode = static_cast<ArenaFreeNode*>(oldPtr); ArenaFreeNode* freeNode = static_cast<ArenaFreeNode*>(oldPtr);
ptrdiff_t posPtr = static_cast<Byte*>(oldPtr) - reinterpret_cast<Byte*>(block); ptrdiff_t posPtr = static_cast<Byte*>(oldPtr) - reinterpret_cast<Byte*>(block);
@@ -244,7 +250,7 @@ namespace Juliet
} }
block->FreeNodes = freeNode; block->FreeNodes = freeNode;
} }
return ArenaPush(arena, newSize, align, shouldBeZeroed); return result;
} }
void ArenaPopTo(NonNullPtr<Arena> arena, size_t position) void ArenaPopTo(NonNullPtr<Arena> arena, size_t position)

View File

@@ -117,28 +117,6 @@ namespace Juliet::UnitTest
ArenaRelease(testArena); 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 // Test reallocate
Arena* arena = ArenaAllocate({ .AllowRealloc = true }); Arena* arena = ArenaAllocate({ .AllowRealloc = true });
@@ -154,6 +132,8 @@ namespace Juliet::UnitTest
Assert(secondCharArray); Assert(secondCharArray);
Assert(thirdCharArray); Assert(thirdCharArray);
Assert(fourthCharArray); Assert(fourthCharArray);
ArenaRelease(arena);
} }
printf("All Paged MemoryArena tests passed.\n"); printf("All Paged MemoryArena tests passed.\n");