Using reallocate for Vector. WIP, unit test not passing
This commit is contained in:
@@ -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.");
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user