Reallocate-Arena #1
@@ -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.");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user