Added a basic MemoryArena.
Added one scratch, one engine and one game arena. Converted the game alloc to arena + the display stuff. WIP Made using Antigravity+gemini
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
<CustomBuild Include="include\Core\Math\Shape.h" />
|
||||
<CustomBuild Include="include\Core\Math\Vector.h" />
|
||||
<CustomBuild Include="include\Core\Memory\Allocator.h" />
|
||||
<CustomBuild Include="include\Core\Memory\MemoryArena.h" />
|
||||
<CustomBuild Include="include\Core\Memory\Utils.h" />
|
||||
<CustomBuild Include="include\Core\Networking\IPAddress.h" />
|
||||
<CustomBuild Include="include\Core\Networking\NetworkPacket.h" />
|
||||
@@ -118,6 +119,9 @@
|
||||
<CustomBuild Include="src\Core\Math\Math_Private.h" />
|
||||
<CustomBuild Include="src\Core\Math\MathRound.cpp" />
|
||||
<CustomBuild Include="src\Core\Memory\Allocator.cpp" />
|
||||
<CustomBuild Include="src\Core\Memory\EngineArena.h" />
|
||||
<CustomBuild Include="src\Core\Memory\MemoryArena.cpp" />
|
||||
<CustomBuild Include="src\Core\Memory\MemoryArenaTests.cpp" />
|
||||
<CustomBuild Include="src\Core\Networking\NetworkPacket.cpp" />
|
||||
<CustomBuild Include="src\Core\Networking\Socket.cpp" />
|
||||
<CustomBuild Include="src\Core\Networking\SocketPlatformImpl.h" />
|
||||
|
||||
@@ -91,6 +91,9 @@
|
||||
<CustomBuild Include="include\Core\Memory\Allocator.h">
|
||||
<Filter>include\Core\Memory</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="include\Core\Memory\MemoryArena.h">
|
||||
<Filter>include\Core\Memory</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="include\Core\Memory\Utils.h">
|
||||
<Filter>include\Core\Memory</Filter>
|
||||
</CustomBuild>
|
||||
@@ -273,6 +276,15 @@
|
||||
<CustomBuild Include="src\Core\Memory\Allocator.cpp">
|
||||
<Filter>src\Core\Memory</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\Memory\EngineArena.h">
|
||||
<Filter>src\Core\Memory</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\Memory\MemoryArena.cpp">
|
||||
<Filter>src\Core\Memory</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\Memory\MemoryArenaTests.cpp">
|
||||
<Filter>src\Core\Memory</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="src\Core\Networking\NetworkPacket.cpp">
|
||||
<Filter>src\Core\Networking</Filter>
|
||||
</CustomBuild>
|
||||
|
||||
@@ -13,6 +13,14 @@ namespace Juliet
|
||||
All = 0xFb
|
||||
};
|
||||
|
||||
struct MemoryArena;
|
||||
|
||||
struct GameInitParams
|
||||
{
|
||||
MemoryArena* GameArena;
|
||||
MemoryArena* ScratchArena;
|
||||
};
|
||||
|
||||
void JulietInit(JulietInit_Flags flags);
|
||||
void JulietShutdown();
|
||||
} // namespace Juliet
|
||||
|
||||
61
Juliet/include/Core/Memory/MemoryArena.h
Normal file
61
Juliet/include/Core/Memory/MemoryArena.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <Juliet.h>
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/Memory/Utils.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
struct MemoryArena
|
||||
{
|
||||
uint8* Data;
|
||||
size_t Size;
|
||||
size_t Offset;
|
||||
};
|
||||
|
||||
JULIET_API void MemoryArenaCreate(MemoryArena* arena, void* backingMemory, size_t size);
|
||||
JULIET_API void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment = 16);
|
||||
JULIET_API void ArenaReset(MemoryArena* arena);
|
||||
JULIET_API size_t ArenaGetMarker(MemoryArena* arena);
|
||||
JULIET_API void ArenaResetToMarker(MemoryArena* arena, size_t marker);
|
||||
|
||||
// --- Global Arenas & Management ---
|
||||
|
||||
// Returns a global arena that resets every frame.
|
||||
JULIET_API MemoryArena* GetScratchArena();
|
||||
|
||||
// Persistent game arena.
|
||||
JULIET_API MemoryArena* GetGameArena();
|
||||
|
||||
// Internal engine function to reset the scratch arena.
|
||||
JULIET_API void ScratchArenaReset();
|
||||
|
||||
// Internal engine function to initialize memory arenas.
|
||||
void MemoryArenasInit();
|
||||
|
||||
// Internal engine function to shutdown memory arenas.
|
||||
void MemoryArenasShutdown();
|
||||
|
||||
template <typename T>
|
||||
inline T* ArenaPushType(MemoryArena* arena)
|
||||
{
|
||||
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T), alignof(T)));
|
||||
if (result)
|
||||
{
|
||||
MemSet(result, 0, sizeof(T));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* ArenaPushArray(MemoryArena* arena, size_t count)
|
||||
{
|
||||
T* result = static_cast<T*>(ArenaPush(arena, sizeof(T) * count, alignof(T)));
|
||||
if (result)
|
||||
{
|
||||
MemSet(result, 0, sizeof(T) * count);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace Juliet
|
||||
0
Juliet/include/Core/Memory/ScratchArena.h
Normal file
0
Juliet/include/Core/Memory/ScratchArena.h
Normal file
@@ -2,6 +2,8 @@
|
||||
#include <Core/HAL/Display/Display_Private.h>
|
||||
#include <Core/HAL/Display/DisplayDevice.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
#include <Core/Memory/EngineArena.h>
|
||||
#include <format>
|
||||
|
||||
namespace Juliet
|
||||
@@ -72,7 +74,8 @@ namespace Juliet
|
||||
{
|
||||
Assert(g_CurrentDisplayDevice->CreatePlatformWindow);
|
||||
|
||||
auto window = static_cast<Window*>(Calloc(1, sizeof(Window)));
|
||||
MemoryArena* arena = GetEngineArena();
|
||||
auto window = ArenaPushType<Window>(arena);
|
||||
if (!window)
|
||||
{
|
||||
return nullptr;
|
||||
@@ -80,9 +83,8 @@ namespace Juliet
|
||||
window->Width = width;
|
||||
window->Height = height;
|
||||
|
||||
// TODO String creator that copy
|
||||
auto titleLen = StringLength(title);
|
||||
auto buffer = static_cast<char*>(Calloc(titleLen, sizeof(char)));
|
||||
auto buffer = ArenaPushArray<char>(arena, titleLen);
|
||||
MemCopy(buffer, title, titleLen);
|
||||
|
||||
window->Title.Data = buffer;
|
||||
@@ -91,7 +93,8 @@ namespace Juliet
|
||||
g_CurrentDisplayDevice->MainWindow = window;
|
||||
if (!g_CurrentDisplayDevice->CreatePlatformWindow(g_CurrentDisplayDevice, window))
|
||||
{
|
||||
// TODO : Destroy
|
||||
// Note: We don't "free" from arena easily, but since this is catastrophic
|
||||
// and persistent, we just leak the small amount of arena space or handle it if we had a marker.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -107,13 +110,12 @@ namespace Juliet
|
||||
|
||||
HideWindow(window);
|
||||
|
||||
// TODO : Free string function
|
||||
SafeFree(window->Title.Data);
|
||||
// We don't free from arena, these are persistent until shutdown.
|
||||
window->Title.Data = nullptr;
|
||||
window->Title.Size = 0;
|
||||
|
||||
g_CurrentDisplayDevice->DestroyPlatformWindow(g_CurrentDisplayDevice, window);
|
||||
|
||||
Free(window.Get());
|
||||
g_CurrentDisplayDevice->MainWindow = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <Core/HAL/Display/Win32/Win32DisplayEvent.h>
|
||||
#include <Core/HAL/Display/Win32/Win32Window.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/EngineArena.h>
|
||||
#include <Core/Memory/Utils.h>
|
||||
|
||||
namespace Juliet::Win32
|
||||
{
|
||||
@@ -12,14 +14,12 @@ namespace Juliet::Win32
|
||||
return true;
|
||||
}
|
||||
void Shutdown(NonNullPtr<DisplayDevice> /*self*/) {}
|
||||
void Free(NonNullPtr<DisplayDevice> self)
|
||||
{
|
||||
Juliet::Free(self.Get());
|
||||
}
|
||||
void Free(NonNullPtr<DisplayDevice> /*self*/) {}
|
||||
|
||||
DisplayDevice* CreateDevice()
|
||||
{
|
||||
auto device = static_cast<DisplayDevice*>(Calloc(1, sizeof(DisplayDevice)));
|
||||
auto device = ArenaPushType<DisplayDevice>(GetEngineArena());
|
||||
|
||||
if (!device)
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <Core/HAL/Display/Win32/Win32Window.h>
|
||||
#include <Core/HAL/Display/Window.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/EngineArena.h>
|
||||
#include <Core/Memory/Utils.h>
|
||||
|
||||
namespace Juliet::Win32
|
||||
{
|
||||
@@ -12,7 +14,8 @@ namespace Juliet::Win32
|
||||
|
||||
bool SetupWindowState(NonNullPtr<DisplayDevice> /*self*/, NonNullPtr<Window> window, HWND handle)
|
||||
{
|
||||
auto state = static_cast<Window32State*>(Calloc(1, sizeof(Window32State)));
|
||||
auto state = ArenaPushType<Window32State>(GetEngineArena());
|
||||
|
||||
window->State = state;
|
||||
state->Handle = handle;
|
||||
state->Window = window;
|
||||
@@ -31,8 +34,6 @@ namespace Juliet::Win32
|
||||
{
|
||||
ReleaseDC(state->Handle, state->HDC);
|
||||
DestroyWindow(state->Handle);
|
||||
|
||||
SafeFree(state);
|
||||
}
|
||||
window->State = nullptr;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/EngineArena.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
#include <Core/Thread/Thread.h>
|
||||
|
||||
#define MAX_TRIES 100
|
||||
@@ -21,11 +23,11 @@ namespace Juliet
|
||||
// First allocate all the full path.
|
||||
// TODO: Add path composition into filesystem + string format + string builder
|
||||
const size_t dllFullPathLength = basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings
|
||||
code.DLLFullPath.Data = static_cast<char*>(Calloc(dllFullPathLength, sizeof(char)));
|
||||
code.DLLFullPath.Data = ArenaPushArray<char>(GetEngineArena(), dllFullPathLength);
|
||||
int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName));
|
||||
if (writtenSize < static_cast<int>(dllFullPathLength) - 1)
|
||||
{
|
||||
SafeFree(code.DLLFullPath.Data);
|
||||
// Arena memory persists, no free needed
|
||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create DLL Full Path");
|
||||
return;
|
||||
}
|
||||
@@ -33,12 +35,12 @@ namespace Juliet
|
||||
|
||||
// Lock filename path
|
||||
const size_t lockPathLength = basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings
|
||||
code.LockFullPath.Data = static_cast<char*>(Calloc(lockPathLength, sizeof(char)));
|
||||
code.LockFullPath.Data = ArenaPushArray<char>(GetEngineArena(), lockPathLength);
|
||||
writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename));
|
||||
if (writtenSize < static_cast<int>(lockPathLength) - 1)
|
||||
{
|
||||
code.LockFullPath.Size = 0;
|
||||
SafeFree(code.LockFullPath.Data);
|
||||
// Arena memory persists, no free needed
|
||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create lock file full path");
|
||||
return;
|
||||
}
|
||||
@@ -52,9 +54,9 @@ namespace Juliet
|
||||
UnloadCode(code);
|
||||
|
||||
code.DLLFullPath.Size = 0;
|
||||
SafeFree(code.DLLFullPath.Data);
|
||||
// Arena memory persists until engine shutdown
|
||||
code.LockFullPath.Size = 0;
|
||||
SafeFree(code.LockFullPath.Data);
|
||||
// Arena memory persists until engine shutdown
|
||||
}
|
||||
|
||||
void ReloadCode(HotReloadCode& code)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <Core/Logging/LogManager.h>
|
||||
#include <Core/Logging/LogTypes.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
@@ -53,7 +54,10 @@ namespace Juliet
|
||||
|
||||
const size_t tempDllMaxBufferSize =
|
||||
basePathLength + StringLength(code.TransientDLLName) + /* _ */ 1 + kTempDLLBufferSizeForID + 1 /* \0 */;
|
||||
auto tempDllPath = static_cast<char*>(Calloc(tempDllMaxBufferSize, sizeof(char)));
|
||||
|
||||
// Allocate from Scratch Arena (transient)
|
||||
auto tempDllPath = ArenaPushArray<char>(GetScratchArena(), tempDllMaxBufferSize);
|
||||
|
||||
for (uint32 attempt = 0; attempt < kMaxAttempts; ++attempt)
|
||||
{
|
||||
// int to char
|
||||
@@ -61,7 +65,7 @@ namespace Juliet
|
||||
int idLength = snprintf(idToStr, sizeof(idToStr), "%u", code.UniqueID);
|
||||
if (idLength < 0)
|
||||
{
|
||||
SafeFree(tempDllPath);
|
||||
// Scratch memory, no free needed
|
||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
|
||||
return;
|
||||
}
|
||||
@@ -70,14 +74,14 @@ namespace Juliet
|
||||
CStr(code.TransientDLLName));
|
||||
if (writtenSize < 0)
|
||||
{
|
||||
SafeFree(tempDllPath);
|
||||
// Scratch memory, no free needed
|
||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
|
||||
return;
|
||||
}
|
||||
|
||||
if (static_cast<size_t>(writtenSize) + 1 < basePathLength + static_cast<size_t>(idLength) + code.TransientDLLName.Size)
|
||||
{
|
||||
SafeFree(tempDllPath);
|
||||
// Scratch memory, no free needed
|
||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
|
||||
return;
|
||||
}
|
||||
@@ -109,7 +113,7 @@ namespace Juliet
|
||||
}
|
||||
}
|
||||
|
||||
SafeFree(tempDllPath);
|
||||
// Scratch memory, no free needed
|
||||
}
|
||||
|
||||
if (!code.IsValid)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <Core/HAL/Display/Display_Private.h>
|
||||
#include <Core/HAL/Filesystem/Filesystem_Private.h>
|
||||
#include <Core/JulietInit.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
@@ -38,9 +39,22 @@ namespace Juliet
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#if JULIET_DEBUG
|
||||
namespace UnitTest
|
||||
{
|
||||
extern void TestMemoryArena();
|
||||
}
|
||||
#endif
|
||||
|
||||
void JulietInit(JulietInit_Flags flags)
|
||||
{
|
||||
// Mandatory systems
|
||||
MemoryArenasInit();
|
||||
|
||||
#if JULIET_DEBUG
|
||||
UnitTest::TestMemoryArena();
|
||||
#endif
|
||||
|
||||
InitFilesystem();
|
||||
|
||||
// Optional systems
|
||||
@@ -61,6 +75,7 @@ namespace Juliet
|
||||
}
|
||||
|
||||
ShutdownFilesystem();
|
||||
MemoryArenasShutdown();
|
||||
}
|
||||
|
||||
} // namespace Juliet
|
||||
|
||||
10
Juliet/src/Core/Memory/EngineArena.h
Normal file
10
Juliet/src/Core/Memory/EngineArena.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
// Persistent engine-only arena.
|
||||
// Not exported to the Game DLL.
|
||||
MemoryArena* GetEngineArena();
|
||||
} // namespace Juliet
|
||||
116
Juliet/src/Core/Memory/MemoryArena.cpp
Normal file
116
Juliet/src/Core/Memory/MemoryArena.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
#include <Core/Memory/Utils.h>
|
||||
|
||||
namespace Juliet
|
||||
{
|
||||
void MemoryArenaCreate(MemoryArena* arena, void* backingMemory, size_t size)
|
||||
{
|
||||
Assert(arena);
|
||||
Assert(backingMemory);
|
||||
arena->Data = static_cast<uint8*>(backingMemory);
|
||||
arena->Size = size;
|
||||
arena->Offset = 0;
|
||||
}
|
||||
|
||||
void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment)
|
||||
{
|
||||
Assert(arena);
|
||||
|
||||
// Alignment must be power of 2
|
||||
Assert((alignment & (alignment - 1)) == 0);
|
||||
|
||||
size_t currentPtr = reinterpret_cast<size_t>(arena->Data + arena->Offset);
|
||||
size_t offset = (currentPtr + (alignment - 1)) & ~(alignment - 1);
|
||||
size_t newOffset = offset - reinterpret_cast<size_t>(arena->Data) + size;
|
||||
|
||||
if (newOffset > arena->Size)
|
||||
{
|
||||
Assert(false, "Memory Arena overflow");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* result = arena->Data + (offset - reinterpret_cast<size_t>(arena->Data));
|
||||
arena->Offset = newOffset;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ArenaReset(MemoryArena* arena)
|
||||
{
|
||||
Assert(arena);
|
||||
arena->Offset = 0;
|
||||
}
|
||||
|
||||
size_t ArenaGetMarker(MemoryArena* arena)
|
||||
{
|
||||
Assert(arena);
|
||||
return arena->Offset;
|
||||
}
|
||||
|
||||
void ArenaResetToMarker(MemoryArena* arena, size_t marker)
|
||||
{
|
||||
Assert(arena);
|
||||
Assert(marker <= arena->Offset);
|
||||
arena->Offset = marker;
|
||||
}
|
||||
|
||||
// --- Global Arenas & Management ---
|
||||
|
||||
namespace
|
||||
{
|
||||
MemoryArena g_ScratchArena;
|
||||
MemoryArena g_EngineArena;
|
||||
MemoryArena g_GameArena;
|
||||
|
||||
void* g_ScratchBacking = nullptr;
|
||||
void* g_EngineBacking = nullptr;
|
||||
void* g_GameBacking = nullptr;
|
||||
|
||||
constexpr size_t kScratchSize = 64 * 1024 * 1024; // 64MB
|
||||
constexpr size_t kEngineSize = 256 * 1024 * 1024; // 256MB
|
||||
constexpr size_t kGameSize = 512 * 1024 * 1024; // 512MB
|
||||
} // namespace
|
||||
|
||||
MemoryArena* GetScratchArena()
|
||||
{
|
||||
return &g_ScratchArena;
|
||||
}
|
||||
|
||||
MemoryArena* GetEngineArena()
|
||||
{
|
||||
return &g_EngineArena;
|
||||
}
|
||||
|
||||
MemoryArena* GetGameArena()
|
||||
{
|
||||
return &g_GameArena;
|
||||
}
|
||||
|
||||
void ScratchArenaReset()
|
||||
{
|
||||
ArenaReset(&g_ScratchArena);
|
||||
}
|
||||
|
||||
void MemoryArenasInit()
|
||||
{
|
||||
// TODO: Use the VirtualAlloc API for this on windows
|
||||
g_ScratchBacking = Malloc(kScratchSize);
|
||||
MemSet(g_ScratchBacking, 0, kScratchSize);
|
||||
g_EngineBacking = Malloc(kEngineSize);
|
||||
MemSet(g_EngineBacking, 0, kEngineSize);
|
||||
g_GameBacking = Malloc(kGameSize);
|
||||
MemSet(g_GameBacking, 0, kGameSize);
|
||||
|
||||
MemoryArenaCreate(&g_ScratchArena, g_ScratchBacking, kScratchSize);
|
||||
MemoryArenaCreate(&g_EngineArena, g_EngineBacking, kEngineSize);
|
||||
MemoryArenaCreate(&g_GameArena, g_GameBacking, kGameSize);
|
||||
}
|
||||
|
||||
void MemoryArenasShutdown()
|
||||
{
|
||||
SafeFree(g_ScratchBacking);
|
||||
SafeFree(g_EngineBacking);
|
||||
SafeFree(g_GameBacking);
|
||||
}
|
||||
} // namespace Juliet
|
||||
67
Juliet/src/Core/Memory/MemoryArenaTests.cpp
Normal file
67
Juliet/src/Core/Memory/MemoryArenaTests.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <cstdio>
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
|
||||
#if JULIET_DEBUG
|
||||
|
||||
namespace Juliet::UnitTest
|
||||
{
|
||||
void TestMemoryArena()
|
||||
{
|
||||
// 1. Core Arena Functionality
|
||||
uint8 buffer[1024];
|
||||
MemoryArena arena;
|
||||
MemoryArenaCreate(&arena, buffer, 1024);
|
||||
|
||||
Assert(arena.Offset == 0);
|
||||
Assert(arena.Size == 1024);
|
||||
|
||||
void* p1 = ArenaPush(&arena, 100);
|
||||
Assert(p1 != nullptr);
|
||||
Assert(arena.Offset >= 100);
|
||||
|
||||
size_t marker = ArenaGetMarker(&arena);
|
||||
void* p2 = ArenaPush(&arena, 200);
|
||||
Assert(p2 != nullptr);
|
||||
Assert(arena.Offset >= marker + 200);
|
||||
|
||||
ArenaResetToMarker(&arena, marker);
|
||||
Assert(arena.Offset == marker);
|
||||
|
||||
ArenaReset(&arena);
|
||||
Assert(arena.Offset == 0);
|
||||
|
||||
// 2. Alignment Test
|
||||
void* p3 = ArenaPush(&arena, 1, 1);
|
||||
[[maybe_unused]] size_t addr = reinterpret_cast<size_t>(p3);
|
||||
void* p4 = ArenaPush(&arena, 1, 16);
|
||||
size_t addr2 = reinterpret_cast<size_t>(p4);
|
||||
Assert((addr2 % 16) == 0);
|
||||
|
||||
// 3. Template Helpers
|
||||
struct TestData
|
||||
{
|
||||
int a;
|
||||
float b;
|
||||
};
|
||||
TestData* data = ArenaPushType<TestData>(&arena);
|
||||
Assert(data != nullptr);
|
||||
data->a = 10;
|
||||
data->b = 20.0f;
|
||||
|
||||
TestData* dataArray = ArenaPushArray<TestData>(&arena, 10);
|
||||
Assert(dataArray != nullptr);
|
||||
|
||||
// 4. Scratch Arena
|
||||
MemoryArena* scratch = GetScratchArena();
|
||||
Assert(scratch != nullptr);
|
||||
void* sp = ArenaPush(scratch, 100);
|
||||
Assert(sp != nullptr);
|
||||
ScratchArenaReset();
|
||||
Assert(scratch->Offset == 0);
|
||||
|
||||
printf("All MemoryArena tests passed.\n");
|
||||
}
|
||||
} // namespace Juliet::UnitTest
|
||||
|
||||
#endif
|
||||
0
Juliet/src/Core/Memory/ScratchArena.cpp
Normal file
0
Juliet/src/Core/Memory/ScratchArena.cpp
Normal file
Reference in New Issue
Block a user