Helios Engine 0.1.0
A modular ECS based data-oriented C++23 game engine
 
Loading...
Searching...
No Matches
system_local_storage.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/core_pch.hpp>
4
14
15#include <concepts>
16#include <cstddef>
17#include <memory>
18#include <ranges>
19#include <utility>
20#include <vector>
21
22namespace helios::ecs::details {
23
24/**
25 * @brief Default initial capacity for the per-system frame allocator (64KB).
26 */
27inline constexpr size_t kDefaultFrameAllocatorCapacity = 64UZ * 1024UZ;
28
29/**
30 * @brief Local storage for system-specific data (commands, events, and temporary allocations).
31 * @details Each system gets its own local storage during execution to avoid contention.
32 * After system execution, the local storage is flushed to the appropriate global queues.
33 *
34 * The frame allocator is designed for temporary per-frame allocations within a system.
35 * It uses a growable allocator internally to automatically expand if the initial capacity is exceeded.
36 * The allocator should be reset at frame boundaries or after each system execution.
37 *
38 * Command metadata uses a standard heap-allocated vector to ensure safe cross-frame and
39 * cross-thread transfer. For systems that need maximum performance and don't transfer
40 * commands across frames, use CreateFrameAllocatedCommandBuffer() which uses the frame allocator.
41 *
42 * @note Not thread-safe - each system has its own instance.
43 */
45public:
48 using FrameCommandVector = std::vector<std::unique_ptr<Command>, FrameCommandAllocator>;
49
50 /**
51 * @brief Constructs system local storage with default frame allocator capacity.
52 */
54
55 /**
56 * @brief Constructs system local storage with specified frame allocator capacity.
57 * @param frame_allocator_capacity Initial capacity for the frame allocator in bytes
58 */
63
66
67 /**
68 * @brief Clears all stored commands and events.
69 * @note Does not reset the frame allocator. Call ResetFrameAllocator() separately.
70 */
71 void Clear();
72
73 /**
74 * @brief Clears commands, events, and resets the frame allocator.
75 * @details Call this at frame boundaries to reclaim all temporary memory.
76 */
77 void ClearAll();
78
79 /**
80 * @brief Adds a command to the local command buffer.
81 * @tparam T Command type
82 * @tparam Args Constructor argument types
83 * @param args Arguments to forward to command constructor
84 */
85 template <CommandTrait T, typename... Args>
87 void EmplaceCommand(Args&&... args) {
88 commands_.push_back(std::make_unique<T>(std::forward<Args>(args)...));
89 }
90
91 /**
92 * @brief Adds a pre-constructed command to the local buffer.
93 * @param command Unique pointer to command
94 */
95 void AddCommand(std::unique_ptr<Command> command);
96
97 /**
98 * @brief Reserves space for commands.
99 * @param capacity Number of commands to reserve space for
100 */
101 void ReserveCommands(size_t capacity) { commands_.reserve(capacity); }
102
103 /**
104 * @brief Writes an event to the local event queue.
105 * @tparam T Event type
106 * @param event Event to store
107 */
108 template <EventTrait T>
109 void WriteEvent(const T& event);
110
111 /**
112 * @brief Writes multiple events to the local event queue in bulk.
113 * @tparam R Range of events
114 * @param events Range of events to store
115 */
116 template <std::ranges::sized_range R>
118 void WriteEventBulk(const R& events);
119
120 /**
121 * @brief Resets the frame allocator, freeing all temporary allocations.
122 * @details Call this at frame boundaries or after system execution to reclaim memory.
123 * @warning All pointers obtained from the frame allocator become invalid after this call.
124 * Do not store references or pointers to frame-allocated data beyond the current frame.
125 */
126 void ResetFrameAllocator() noexcept { frame_allocator_.Reset(); }
127
128 /**
129 * @brief Creates a frame-allocated command allocator.
130 * @details Use this for temporary command buffers that don't outlive the current frame.
131 * More efficient than heap allocation for short-lived command storage.
132 * @return Frame command allocator instance
133 */
137
138 /**
139 * @brief Checks if both commands and events are empty.
140 * @return True if no commands or events are stored, false otherwise
141 */
142 [[nodiscard]] bool Empty() const noexcept { return commands_.empty() && events_.Empty(); }
143
144 /**
145 * @brief Gets the number of commands in the buffer.
146 * @return Count of commands
147 */
148 [[nodiscard]] size_t CommandCount() const noexcept { return commands_.size(); }
149
150 /**
151 * @brief Gets frame allocator statistics.
152 * @return Allocator statistics with current usage information
153 */
155
156 /**
157 * @brief Gets total capacity of the frame allocator across all internal allocators.
158 * @return Total capacity in bytes
159 */
160 [[nodiscard]] size_t FrameAllocatorCapacity() const noexcept { return frame_allocator_.TotalCapacity(); }
161
162 /**
163 * @brief Gets reference to the command buffer.
164 * @return Reference to command vector
165 */
166 [[nodiscard]] auto GetCommands() noexcept -> std::vector<std::unique_ptr<Command>>& { return commands_; }
167
168 /**
169 * @brief Gets const reference to the command buffer.
170 * @return Const reference to command vector
171 */
172 [[nodiscard]] auto GetCommands() const noexcept -> const std::vector<std::unique_ptr<Command>>& { return commands_; }
173
174 /**
175 * @brief Gets reference to the event queue.
176 * @return Reference to event queue
177 */
178 [[nodiscard]] EventQueue& GetEventQueue() noexcept { return events_; }
179
180 /**
181 * @brief Gets const reference to the event queue.
182 * @return Const reference to event queue
183 */
184 [[nodiscard]] const EventQueue& GetEventQueue() const noexcept { return events_; }
185
186 /**
187 * @brief Gets reference to the frame allocator.
188 * @details Use this allocator for temporary per-frame allocations that don't need individual deallocation.
189 * Memory is reclaimed when ResetFrameAllocator() is called.
190 * @return Reference to the growable frame allocator
191 */
192 [[nodiscard]] FrameAllocatorType& FrameAllocator() noexcept { return frame_allocator_; }
193
194 /**
195 * @brief Gets const reference to the frame allocator.
196 * @warning Data allocated with the frame allocator is only valid for the current frame.
197 * @return Const reference to the growable frame allocator
198 */
199 [[nodiscard]] const FrameAllocatorType& FrameAllocator() const noexcept { return frame_allocator_; }
200
201private:
202 std::vector<std::unique_ptr<Command>> commands_; ///< Local command buffer
203 EventQueue events_; ///< Local event queue
204 FrameAllocatorType frame_allocator_; ///< Per-system frame allocator for temporary allocations
205};
206
207inline void SystemLocalStorage::AddCommand(std::unique_ptr<Command> command) {
208 HELIOS_ASSERT(command != nullptr, "Failed to add command: command is null!");
209 commands_.push_back(std::move(command));
210}
211
213 commands_.clear();
214 events_.Clear();
215}
216
218 Clear();
220}
221
222template <EventTrait T>
224 if (!events_.IsRegistered<T>()) {
225 events_.Register<T>();
226 }
227 events_.Write(event);
228}
229
230template <std::ranges::sized_range R>
233 using EventType = std::ranges::range_value_t<R>;
234 if (!events_.IsRegistered<EventType>()) {
235 events_.Register<EventType>();
236 }
237 events_.WriteBulk(events);
238}
239
240} // namespace helios::ecs::details
#define HELIOS_ASSERT(condition,...)
Assertion macro that aborts execution in debug builds.
Definition assert.hpp:140
Base class for all commands to be executed in the world.
Definition command.hpp:12
Queue for managing multiple event types.
void WriteBulk(const R &events)
Writes multiple events to the queue in bulk.
bool Empty() const noexcept
Checks if the queue is empty.
void Clear() noexcept
Clears all events from the queue and removes registrations.
void Register()
Registers an event type with the queue.
void Write(const T &event)
Writes a single event to the queue.
bool IsRegistered() const
Checks if an event type is registered.
Local storage for system-specific data (commands, events, and temporary allocations).
SystemLocalStorage()
Constructs system local storage with default frame allocator capacity.
void Clear()
Clears all stored commands and events.
void WriteEvent(const T &event)
Writes an event to the local event queue.
void WriteEventBulk(const R &events)
Writes multiple events to the local event queue in bulk.
void EmplaceCommand(Args &&... args)
Adds a command to the local command buffer.
const EventQueue & GetEventQueue() const noexcept
Gets const reference to the event queue.
size_t FrameAllocatorCapacity() const noexcept
Gets total capacity of the frame allocator across all internal allocators.
size_t CommandCount() const noexcept
Gets the number of commands in the buffer.
auto GetCommands() const noexcept -> const std::vector< std::unique_ptr< Command > > &
Gets const reference to the command buffer.
memory::AllocatorStats FrameAllocatorStats() const noexcept
Gets frame allocator statistics.
memory::STLGrowableAllocator< std::unique_ptr< Command >, memory::FrameAllocator > FrameCommandAllocator
FrameAllocatorType & FrameAllocator() noexcept
Gets reference to the frame allocator.
EventQueue & GetEventQueue() noexcept
Gets reference to the event queue.
SystemLocalStorage(size_t frame_allocator_capacity)
Constructs system local storage with specified frame allocator capacity.
memory::GrowableAllocator< memory::FrameAllocator > FrameAllocatorType
void ReserveCommands(size_t capacity)
Reserves space for commands.
void AddCommand(std::unique_ptr< Command > command)
Adds a pre-constructed command to the local buffer.
const FrameAllocatorType & FrameAllocator() const noexcept
Gets const reference to the frame allocator.
SystemLocalStorage(const SystemLocalStorage &)=delete
void ResetFrameAllocator() noexcept
Resets the frame allocator, freeing all temporary allocations.
auto GetCommands() noexcept -> std::vector< std::unique_ptr< Command > > &
Gets reference to the command buffer.
void ClearAll()
Clears commands, events, and resets the frame allocator.
std::vector< std::unique_ptr< Command >, FrameCommandAllocator > FrameCommandVector
FrameCommandAllocator CreateFrameCommandAllocator() noexcept
Creates a frame-allocated command allocator.
bool Empty() const noexcept
Checks if both commands and events are empty.
SystemLocalStorage(SystemLocalStorage &&) noexcept=default
Linear allocator that clears every frame.
size_t TotalCapacity() const noexcept
Gets the total capacity across all allocator instances.
AllocatorStats Stats() const noexcept
Gets combined statistics for all allocator instances.
void Reset() noexcept
Resets all allocator instances.
STL-compatible allocator adapter for custom allocators.
Concept for valid event types.
Definition event.hpp:44
constexpr size_t kDefaultFrameAllocatorCapacity
Default initial capacity for the per-system frame allocator (64KB).
BasicQuery< World, Allocator, Components... > Query
Type alias for query with mutable world access.
Definition query.hpp:2481
STL namespace.
Statistics for tracking allocator usage.