Simplified VectorArena to always take an arena and to not support change of capacity

This commit is contained in:
2026-07-22 22:12:05 -04:00
parent c0d40ef3e4
commit 9c8f9bff41
12 changed files with 213 additions and 197 deletions
+92
View File
@@ -0,0 +1,92 @@
# Workload Analysis: Removing C++ Stdlib & Migrating to Pure C
This analysis outlines the required workload, technical impact, and migration strategy for:
1. Removing all standard C++ library dependencies (`std::*`) from the Juliet codebase.
2. Moving completely from C++ to pure C.
---
## 1. Scope Overview
The repository consists of multiple sub-projects (**Juliet Core Engine**, **JulietApp**, **Game**, **Romeo**, and **External dependencies**). Eliminating stdlib dependencies versus migrating completely to pure C represent two distinct milestones:
| Metric / Domain | Task 1: Eliminate C++ stdlib | Task 2: Pure C Migration |
| :--- | :--- | :--- |
| **Language Target** | C++20 (without standard libraries) | Pure C (C11 / C99 standard) |
| **Containers & Math** | Custom templates (`Vector<T>`, `HashTable<K,V>`, custom algorithms) | C structs + `void*` / macro templates + explicit functions |
| **Threading & Sync** | Win32 / OS APIs directly (`CreateThread`, `SRWLOCK`) | Native OS APIs (`CreateThread`, `SRWLOCK`, atomic primitives) |
| **External Third-Party** | Native Direct3D 12, ImGui | `cimgui` (C bindings), DirectX C COM interfaces (`ID3D12Device*`) |
| **OOP & Templates** | Kept intact | Struct-based vtables, no function overloading, no references (`&`) |
---
## 2. Phase 1: Removing C++ stdlib Dependencies
### A. Containers & Utility Replacement
- **Current Usages**: `<vector>`, `<queue>`, `<list>`, `<forward_list>`, `<algorithm>`, `<bit>`, `<concepts>`, `<type_traits>`, `<source_location>`.
- **Workload**:
1. **Containers**: Replace container implementations (such as `Juliet/include/Core/Container/Vector.h`, which currently includes `<vector>`) with custom dynamically resizing arrays / buffer allocators backed by `MemoryArena`.
2. **Type Traits & Concepts**: Replace `<type_traits>` and `<concepts>` usage in files like `Game/Entity/Entity.h` with compiler intrinsics (e.g. `__is_enum`, `__is_base_of`) or internal lightweight trait structures.
3. **Algorithms & Math Utilities**: Implement custom `Min`, `Max`, `Clamp`, `Sort`, and `Swap` functions in `CoreUtils.h` or custom inline header helpers.
### B. Threading & Synchronization
- **Current Usages**: `<thread>`, `<mutex>`, `std::thread`, `std::mutex`, `std::lock_guard`.
- **Workload**:
1. Replace `<thread>` in `Thread.h` and `Romeo/src/main.cpp` with platform abstraction wrappers using Win32 `CreateThread` / `CloseHandle`.
2. Replace `<mutex>` in `Mutex.h` with `SRWLOCK` or `CRITICAL_SECTION`.
### C. Time & File I/O
- **Current Usages**: `<chrono>`, `<cstdio>`, `<fstream>`, `<ios>`, `<iosfwd>`, `<cstdlib>`.
- **Workload**:
1. Replace `<chrono>` in `LogManager.cpp` and `SystemEvent.cpp` with `QueryPerformanceCounter` / `QueryPerformanceFrequency` on Windows.
2. Standardize filesystem I/O on Win32 API (`CreateFileW`, `ReadFile`, `WriteFile`) or minimal C runtime headers (`<stdio.h>`, `<stdlib.h>`, `<string.h>`).
### D. Memory Allocators & RTTI
- **Current Usages**: `<new>`, `<typeinfo>` (`typeid` in `MemoryArena.h`), `<memory>`.
- **Workload**:
1. Replace placement `new` with custom inline placement functions or custom explicit initialization methods.
2. Replace `typeid` / `type_info` usages with custom type hashing or enum type IDs.
---
## 3. Phase 2: Complete Migration to C
Transitioning fully to C requires refactoring away all C++ language constructs.
### A. DirectX 12 & Agility SDK Integration
- **D3D12 Header Interface**: Switch from C++ COM smart pointers / methods (`device->CreateCommandAllocator(...)`) to standard C COM interfaces (`ID3D12Device_CreateCommandAllocator(device, ...)`).
- **D3DX12 Helper Library**: `d3dx12_state_object.h` and helper files rely heavily on stdlib (`std::vector`, `std::memory`, C++ structures). These must be rewritten in plain C or replaced with native DirectX 12 C struct initializers.
### B. UI Framework (ImGui)
- Dear ImGui is natively C++.
- **Workload**: Switch from standard `imgui.h` / `imgui_stdlib.h` to [cimgui](https://github.com/cimgui/cimgui) (C-compatible wrappers for ImGui) or maintain a minimal C++ bridge file specifically for ImGui.
### C. Codebase Refactoring (Language Paradigm)
1. **Classes to Structs**: Convert classes in `Juliet` core, `Game`, and `Romeo` to C structs.
2. **Virtual Functions**: Replace polymorphism with explicit `void*` context pointers and function pointer tables (vtables).
3. **Namespaces & Function Overloading**: Prefix function names (e.g., `Juliet_Log_Info(...)`) as C does not support namespaces or function overloading.
4. **Member Functions to Free Functions**: Convert `obj.Method(args)` to `Method(&obj, args)`.
5. **No Reference Arguments (`&`)**: Replace all pass-by-reference parameters with explicit pointers (`*`).
6. **Casting Rules**: Remove `static_cast` and `reinterpret_cast` in favor of standard C explicit casts `(Type)val`.
### D. Build System (`Romeo.bff` / `fbuild.bff`)
- Update compiler settings in FastBuild (`.bff` files) and Visual Studio project settings from `/std:c++20` to C compiler flags (`/std:c11` or `/TC`).
---
## 4. Estimated Workload Matrix
| Task Module | Complexity | Estimated Relative Effort | Risks / Key Considerations |
| :--- | :--- | :--- | :--- |
| **1. Stdlib-Free Containers & Utils** | Moderate | ~15% | Custom array/hash table implementation. |
| **2. OS Threading & Time Abstraction** | Low-Moderate | ~10% | Clean Windows API replacements (`QueryPerformanceCounter`, `SRWLOCK`). |
| **3. C Struct & Syntax Refactoring** | High | ~40% | Large volume of mechanical refactoring (references, namespaces, overloading, methods). |
| **4. Graphics / D3D12 C Refactoring** | High | ~20% | `d3dx12` heavily relies on C++ templates/stdlib; rewriting helper structs in C. |
| **5. ImGui / Romeo GUI Integration** | Moderate | ~15% | Needs `cimgui` integration or a C-wrapper boundary. |
---
## 5. Recommendation & Phasing
1. **Step 1 (Stdlib Removal)**: Keep C++20 language features (classes, templates, member methods), but remove all stdlib inclusions (`<vector>`, `<thread>`, `<chrono>`, `<algorithm>`). Replace them with custom `Juliet` engine primitives.
2. **Step 2 (Evaluate C Migration)**: Re-evaluate if moving to pure C provides enough benefit vs. keeping a clean, stdlib-free C++ subset ("C with Classes" / stdlib-free C++).
+54 -82
View File
@@ -2,50 +2,29 @@
#include <Core/Common/NonNullPtr.h>
#include <Core/Memory/MemoryArena.h>
#include <vector>
namespace Juliet
{
template <typename Type, size_t ReserveSize = 16, bool AllowRealloc = false>
template <typename Type, size_t ReserveSize = 16>
struct VectorArena
{
void Create(JULIET_DEBUG_PARAM_FIRST(const char* name = nullptr))
{
Assert(!Arena);
static_assert(AllowRealloc == false);
DataFirst = DataLast = nullptr;
Count = 0;
JULIET_DEBUG_ONLY(Name = name ? name : Name;)
ArenaParams params{ .AllowRealloc = AllowRealloc JULIET_DEBUG_PARAM(.CanReserveMore = false) };
Arena = ArenaAllocate(params JULIET_DEBUG_PARAM(Name));
InternalArena = true;
Reserve(ReserveSize);
}
void Create(NonNullPtr<Arena> arena JULIET_DEBUG_PARAM(const char* name = nullptr))
{
Assert(!Arena);
JULIET_DEBUG_ONLY(Name = name ? name : Name;)
DataFirst = DataLast = nullptr;
DataFirst = DataLast = Data = nullptr;
Count = 0;
Arena = arena.Get();
InternalArena = false;
Capacity = 0;
Arena = arena;
Reserve(ReserveSize);
}
void Destroy()
{
if (InternalArena)
{
ArenaRelease(Arena);
}
DataFirst = DataLast = nullptr;
DataFirst = DataLast = Data = nullptr;
Count = 0;
Capacity = 0;
Arena = nullptr;
@@ -53,38 +32,33 @@ namespace Juliet
void Reserve(size_t newCapacity)
{
if (newCapacity > Capacity)
{
Assert(Arena);
if (Data == nullptr)
{
Data = ArenaPushArray<Type>(Arena, newCapacity JULIET_DEBUG_PARAM(Name));
}
else if constexpr (AllowRealloc)
{
if (!InternalArena)
{
DataFirst = Data =
static_cast<Type*>(ArenaReallocate(Arena, Data, Capacity * sizeof(Type), newCapacity * sizeof(Type),
AlignOf(Type), true JULIET_DEBUG_PARAM("VectorRealloc")));
DataLast = Data + Count - 1;
}
}
Capacity = newCapacity;
}
else
{
Assert(newCapacity <= Capacity && "VectorArena capacity exceeded! Reallocation is disabled.");
}
}
void Resize(size_t newCount)
{
Assert(Arena);
if (newCount == Count)
{
return;
}
if (newCount > Capacity)
if (Data == nullptr)
{
Reserve(newCount);
size_t initialCapacity = newCount > ReserveSize ? newCount : ReserveSize;
Reserve(initialCapacity);
}
Assert(newCount <= Capacity && "VectorArena capacity exceeded!");
Count = newCount;
if (Count > 0)
@@ -101,20 +75,21 @@ namespace Juliet
void PushBack(const Type* buffer, size_t amount)
{
Assert(Arena);
Assert(buffer || amount == 0);
if (Count + amount > Capacity)
if (amount == 0)
{
if (Capacity == 0 && Count + amount < ReserveSize)
return;
}
if (Data == nullptr)
{
Reserve(ReserveSize);
}
else
{
size_t newCapacity = Max(Capacity * 2, AlignPow2(Capacity + amount, AlignOf(Type)));
Reserve(newCapacity);
}
size_t initialCapacity = amount > ReserveSize ? amount : ReserveSize;
Reserve(initialCapacity);
}
Assert(Count + amount <= Capacity && "VectorArena capacity exceeded!");
Type* dst = Data + Count;
MemCopy(dst, buffer, amount * sizeof(Type));
@@ -122,7 +97,7 @@ namespace Juliet
{
DataFirst = dst;
}
DataLast = dst + amount;
DataLast = dst + amount - 1;
Count += amount;
}
@@ -130,11 +105,13 @@ namespace Juliet
{
Assert(Arena);
if (Count + 1 > Capacity)
if (Data == nullptr)
{
Reserve(Capacity == 0 ? ReserveSize : Capacity * 2);
Reserve(ReserveSize);
}
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
Type* entry = Data + Count;
*entry = value;
@@ -150,11 +127,13 @@ namespace Juliet
{
Assert(Arena);
if (Count + 1 > Capacity)
if (Data == nullptr)
{
Reserve(Capacity == 0 ? ReserveSize : Capacity * 2);
Reserve(ReserveSize);
}
Assert(Count + 1 <= Capacity && "VectorArena capacity exceeded!");
Type* entry = Data + Count;
*entry = std::move(value);
@@ -193,44 +172,37 @@ namespace Juliet
{
Assert(Arena);
if (InternalArena)
{
ArenaClear(Arena);
Data = nullptr;
Capacity = 0;
Reserve(ReserveSize);
}
DataFirst = DataLast = nullptr;
Count = 0;
}
bool IsEmpty() const { return Count == 0; }
[[nodiscard]] bool IsEmpty() const { return Count == 0; }
// C++ Accessors for loop supports and Index based access
Type& operator[](size_t index) { return DataFirst[index]; }
const Type& operator[](size_t index) const { return DataFirst[index]; }
[[nodiscard]] Type& operator[](size_t index) { return DataFirst[index]; }
[[nodiscard]] const Type& operator[](size_t index) const { return DataFirst[index]; }
Type* begin() { return DataFirst; }
Type* end() { return DataFirst + Count; }
[[nodiscard]] Type* begin() { return DataFirst; }
[[nodiscard]] Type* end() { return DataFirst + Count; }
const Type* begin() const { return DataFirst; }
const Type* end() const { return DataFirst + Count; }
[[nodiscard]] const Type* begin() const { return DataFirst; }
[[nodiscard]] const Type* end() const { return DataFirst + Count; }
Type* First() { return DataFirst; }
Type* Front() { return DataFirst; }
Type* Last() { return DataLast; }
Type* Back() { return DataLast; }
[[nodiscard]] Type* First() { return DataFirst; }
[[nodiscard]] Type* Front() { return DataFirst; }
[[nodiscard]] Type* Last() { return DataLast; }
[[nodiscard]] Type* Back() { return DataLast; }
[[nodiscard]] Type* DataPtr() { return Data; }
[[nodiscard]] const Type* DataPtr() const { return Data; }
size_t Size() const { return Count; }
[[nodiscard]] size_t Size() const { return Count; }
Arena* Arena;
Type* DataFirst;
Type* DataLast;
Type* Data;
size_t Count;
size_t Capacity;
bool InternalArena : 1;
Arena* Arena = nullptr;
Type* DataFirst = nullptr;
Type* DataLast = nullptr;
Type* Data = nullptr;
size_t Count = 0;
size_t Capacity = 0;
JULIET_DEBUG_ONLY(const char* Name = "VectorArena";)
};
static_assert(std::is_standard_layout_v<VectorArena<int>>,
@@ -5,25 +5,20 @@
namespace Juliet
{
// TODO Use VectorArena
template <typename T>
class Vector : public std::vector<T>
{
};
class NetworkPacket
{
public:
NetworkPacket();
NetworkPacket(Arena& arena);
virtual ~NetworkPacket();
NetworkPacket(NetworkPacket&);
NetworkPacket& operator=(const NetworkPacket&);
NetworkPacket(NetworkPacket&&) noexcept;
NetworkPacket& operator=(NetworkPacket&&) noexcept;
ByteBuffer GetRawData();
void Create(Arena& arena);
// Unpack
[[nodiscard]] ByteBuffer GetRawData();
// Pack
NetworkPacket& operator<<(uint32 value);
@@ -35,7 +30,7 @@ namespace Juliet
friend class TcpSocket;
private:
Vector<Byte> Data;
VectorArena<Byte, 4096> Data;
size_t PartialSendIndex = 0;
};
} // namespace Juliet
+4 -5
View File
@@ -30,11 +30,10 @@ namespace Juliet
struct MeshRenderer
{
// Note we prevent realloc for now.
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
VectorArena<Index, kDefaultIndexCount, false> Indices;
VectorArena<PointLight, kDefaultLightCount, false> PointLights;
VectorArena<Mesh, kDefaultMeshNumber> Meshes;
VectorArena<Vertex, kDefaultVertexCount> Vertices;
VectorArena<Index, kDefaultIndexCount> Indices;
VectorArena<PointLight, kDefaultLightCount> PointLights;
GraphicsBuffer* VertexBuffer;
GraphicsBuffer* IndexBuffer;
+12 -5
View File
@@ -7,17 +7,26 @@
namespace Juliet
{
NetworkPacket::NetworkPacket() = default;
NetworkPacket::NetworkPacket(Arena& arena)
{
Data.Create(&arena);
}
NetworkPacket::~NetworkPacket() = default;
NetworkPacket::NetworkPacket(NetworkPacket&) = default;
NetworkPacket& NetworkPacket::operator=(const NetworkPacket&) = default;
NetworkPacket::NetworkPacket(NetworkPacket&&) noexcept = default;
NetworkPacket& NetworkPacket::operator=(NetworkPacket&&) noexcept = default;
void NetworkPacket::Create(Arena& arena)
{
Data.Create(&arena);
}
ByteBuffer NetworkPacket::GetRawData()
{
ByteBuffer buffer{};
buffer.Data = Data.data();
buffer.Size = Data.size();
buffer.Data = Data.DataPtr();
buffer.Size = Data.Size();
return buffer;
}
@@ -52,9 +61,7 @@ namespace Juliet
{
if (buffer.Data && (buffer.Size > 0))
{
const auto* begin = reinterpret_cast<const std::byte*>(buffer.Data);
const auto* end = begin + buffer.Size;
Data.insert(Data.end(), begin, end);
Data.PushBack(TO_BUFFER(buffer.Data), buffer.Size);
}
}
+3
View File
@@ -27,6 +27,7 @@ namespace Juliet
// Because of that we will send the size of the packet first before sending the data.
// TODO Use scratch allocator.
/*
Vector<Byte> scratchVector;
scratchVector.resize(buffer.Size + sizeof(uint32));
@@ -52,6 +53,8 @@ namespace Juliet
}
return messageStatus;
*/
return {};
}
Socket::RequestStatus TcpSocket::Send(ByteBuffer buffer)
+5 -3
View File
@@ -40,13 +40,14 @@ namespace Juliet::Debug
};
// Static Vector for lookup
VectorArena<PagedArenaStateEntry> s_PagedArenaStates;
VectorArena<PagedArenaStateEntry, Kilobytes(1024)> s_PagedArenaStates;
PagedArenaDebugState& GetPagedArenaState(const Arena* arena)
{
if (s_PagedArenaStates.Arena == nullptr)
{
s_PagedArenaStates.Create(JULIET_DEBUG_ONLY("DebugState States"));
Arena* pagedArenaStates = ArenaAllocate({} JULIET_DEBUG_ONLY(, "DebugState States"));
s_PagedArenaStates.Create(pagedArenaStates);
}
for (auto& entry : s_PagedArenaStates)
@@ -104,7 +105,8 @@ namespace Juliet::Debug
static VectorArena<const Arena*> blocks;
if (blocks.Arena == nullptr)
{
blocks.Create(JULIET_DEBUG_ONLY("DebugState Blocks"));
Arena* pagedArenaStates = ArenaAllocate({} JULIET_DEBUG_ONLY(, "DebugState Blocks"));
blocks.Create(pagedArenaStates);
}
blocks.Clear();
+4 -4
View File
@@ -22,10 +22,10 @@ namespace Juliet
GraphicsBuffer* TransformsBuffer = nullptr;
GraphicsTransferBuffer* LoadCopyBuffer = nullptr;
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
VectorArena<Index, kDefaultIndexCount, false> Indices;
VectorArena<PointLight, kDefaultLightCount, false> PointLights;
VectorArena<Mesh, kDefaultMeshNumber> Meshes;
VectorArena<Vertex, kDefaultVertexCount> Vertices;
VectorArena<Index, kDefaultIndexCount> Indices;
VectorArena<PointLight, kDefaultLightCount> PointLights;
PointLight* MappedLights = nullptr;
Matrix* MappedTransforms = nullptr;
@@ -9,8 +9,8 @@ namespace Juliet::UnitTest
{
namespace
{
template <typename T, size_t ReserveSize, bool AllowRealloc>
inline void VerifyVectorState(const VectorArena<T, ReserveSize, AllowRealloc>& vec, size_t expectedCount)
template <typename T, size_t ReserveSize>
inline void VerifyVectorState(const VectorArena<T, ReserveSize>& vec, size_t expectedCount)
{
Assert(vec.Size() == expectedCount);
@@ -29,10 +29,13 @@ namespace Juliet::UnitTest
void VectorUnitTest()
{
ArenaParams params{};
Arena* testArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorUnitTestArena"));
// Test 1: Integer VectorArena (Basic Operations)
{
VectorArena<int> vec = {};
vec.Create();
vec.Create(testArena);
VerifyVectorState(vec, 0);
vec.PushBack(10);
@@ -65,7 +68,7 @@ namespace Juliet::UnitTest
// Test 2: RemoveAtFast
{
VectorArena<int> vec = {};
vec.Create();
vec.Create(testArena);
vec.PushBack(10);
vec.PushBack(20);
@@ -95,7 +98,7 @@ namespace Juliet::UnitTest
// Test 3: Clear and Reuse (Pointer State Check)
{
VectorArena<int> vec = {};
vec.Create();
vec.Create(testArena);
vec.PushBack(100);
vec.PushBack(200);
@@ -127,7 +130,7 @@ namespace Juliet::UnitTest
};
VectorArena<TestItem> vec = {};
vec.Create();
vec.Create(testArena);
VerifyVectorState(vec, 0);
@@ -145,39 +148,7 @@ namespace Juliet::UnitTest
vec.Destroy();
}
// Test 5: Reallocation Support (AllowRealloc = true)
{
// Initial capacity 4, allow realloc
ArenaParams params{ .AllowRealloc = true };
Arena* externalArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorTest"));
VectorArena<int, 4, true> vec = {};
vec.Create(externalArena);
Assert(vec.Capacity == 4);
vec.PushBack(1);
vec.PushBack(2);
vec.PushBack(3);
vec.PushBack(4);
Assert(vec.Capacity == 4);
// Trigger realloc
vec.PushBack(5);
Assert(vec.Capacity >= 5); // Should have grown (likely doubled to 8)
VerifyVectorState(vec, 5);
Assert(vec[0] == 1);
Assert(vec[1] == 2);
Assert(vec[2] == 3);
Assert(vec[3] == 4);
Assert(vec[4] == 5);
vec.Destroy();
ArenaRelease(externalArena);
}
// Test 6: Move Semantics
// Test 5: Move Semantics
{
struct MoveOnly
{
@@ -207,10 +178,8 @@ namespace Juliet::UnitTest
}
};
VectorArena<MoveOnly, 4, true> vec = {};
ArenaParams params{ .AllowRealloc = true };
Arena* externalArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorTest"));
NonNullPtr<Arena> validArena(externalArena);
VectorArena<MoveOnly, 4> vec = {};
NonNullPtr<Arena> validArena(testArena);
vec.Create(validArena);
MoveOnly item1(10);
@@ -222,16 +191,13 @@ namespace Juliet::UnitTest
Assert(!vec[0].MovedFrom);
vec.Destroy();
ArenaRelease(externalArena);
}
// Test 7: Resize Behavior
// Test 6: Resize Behavior
{
ArenaParams params{ .AllowRealloc = true };
Arena* externalArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorTest"));
NonNullPtr<Arena> validArena(externalArena);
NonNullPtr<Arena> validArena(testArena);
VectorArena<int, 4, true> vec = {};
VectorArena<int, 4> vec = {};
vec.Create(validArena);
vec.PushBack(1);
@@ -243,42 +209,21 @@ namespace Juliet::UnitTest
Assert(vec.Size() == 1);
Assert(vec[0] == 1);
// Resize larger
// Resize larger up to max capacity
vec.Resize(4);
Assert(vec.Size() == 4);
Assert(vec[0] == 1);
vec.Destroy();
ArenaRelease(externalArena);
}
// Test 8: External Arena Usage
// Test 7: External Arena Usage & Volume Test within capacity
{
ArenaParams params{ .AllowRealloc = true };
Arena* externalArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorTest"));
NonNullPtr<Arena> validArena(externalArena);
NonNullPtr<Arena> validArena(testArena);
VectorArena<int> vec = {};
VectorArena<int, 100> vec = {};
vec.Create(validArena); // Pass external arena
vec.PushBack(42);
Assert(vec.Size() == 1);
Assert(vec[0] == 42);
vec.Destroy();
ArenaRelease(externalArena);
}
// Test 9: Volume Test (100 items with Realloc)
{
ArenaParams params{ .AllowRealloc = true };
Arena* externalArena = ArenaAllocate(params JULIET_DEBUG_ONLY(, "VectorTest"));
NonNullPtr<Arena> validArena(externalArena);
VectorArena<int, 4, true> vec = {};
vec.Create(validArena);
// Push 100 items -> Should realloc multiple times
for (int i = 0; i < 100; ++i)
{
vec.PushBack(i);
@@ -291,8 +236,9 @@ namespace Juliet::UnitTest
}
vec.Destroy();
ArenaRelease(externalArena);
}
ArenaRelease(testArena);
}
} // namespace Juliet::UnitTest
#endif
+1 -1
View File
@@ -25,7 +25,7 @@ namespace Romeo
struct Database
{
Juliet::VectorArena<FileEntry, 512, true> Entries = {};
Juliet::VectorArena<FileEntry, 512> Entries = {};
Juliet::Arena* DbArena = nullptr;
Juliet::Mutex Mutex;
};
+2 -2
View File
@@ -31,8 +31,8 @@ namespace Romeo
double NumVal = 0.0;
Juliet::String StrVal = {};
Juliet::VectorArena<JsonValue, 32, true> ArrayVal = {};
Juliet::VectorArena<JsonKeyValue, 32, true> ObjectVal = {};
Juliet::VectorArena<JsonValue, 32> ArrayVal = {};
Juliet::VectorArena<JsonKeyValue, 32> ObjectVal = {};
};
// Parses a JSON string. Memory is allocated on the provided arena.
+3 -3
View File
@@ -410,7 +410,7 @@ namespace Romeo
static void ParseSymbolsFromFile(
Juliet::Arena* arena,
const Juliet::String& filePath,
Juliet::VectorArena<ParsedSymbol, 128, true>& outSymbols
Juliet::VectorArena<ParsedSymbol, 128>& outSymbols
)
{
Assert(arena != nullptr);
@@ -726,7 +726,7 @@ namespace Romeo
static void FormatAndWriteSymbols(StringBuilder& sb, Juliet::Arena* arena, const Juliet::String& filePath)
{
printf("Romeo: FormatAndWriteSymbols start for %.*s\n", static_cast<int>(filePath.Size), CStr(filePath));
Juliet::VectorArena<ParsedSymbol, 128, true> symbols = {};
Juliet::VectorArena<ParsedSymbol, 128> symbols = {};
symbols.Create(arena JULIET_DEBUG_ONLY(, "ParsedSymbols"));
printf("Romeo: Calling ParseSymbolsFromFile...\n");
@@ -741,7 +741,7 @@ namespace Romeo
// Collect all distinct namespaces
printf("Romeo: Collecting namespaces...\n");
Juliet::VectorArena<Juliet::String, 16, true> namespaces = {};
Juliet::VectorArena<Juliet::String, 16> namespaces = {};
namespaces.Create(arena JULIET_DEBUG_ONLY(, "NamespacesList"));
for (const ParsedSymbol& sym : symbols)