Helios Engine 0.1.0
A modular ECS based data-oriented C++23 game engine
 
Loading...
Searching...
No Matches
world_command_buffer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/core_pch.hpp>
4
12
13#include <algorithm>
14#include <concepts>
15#include <memory>
16#include <ranges>
17#include <utility>
18#include <vector>
19
20namespace helios::ecs {
21
22/**
23 * @brief Command buffer to record world operations for deferred execution.
24 * @details Provides a convenient interface for recording operations that will be executed
25 * during World::Update(). All operations are queued locally and flushed to SystemLocalStorage
26 * on destruction or explicit Flush() call.
27 *
28 * Supports custom allocators for internal storage, enabling use of frame allocators
29 * for zero-overhead temporary allocations within systems.
30 *
31 * @note Not thread-safe. Created per system.
32 * @tparam Allocator Allocator type for internal command pointer storage
33 *
34 * @example
35 * @code
36 * void MySystem(app::SystemContext& ctx) {
37 * auto cmd = ctx.Commands(); // Uses frame allocator by default
38 * cmd.Destroy(entity);
39 * cmd.ClearEvents<MyEvent>();
40 * // Commands are flushed automatically when cmd goes out of scope
41 * }
42 * @endcode
43 */
44template <typename Allocator = std::allocator<std::unique_ptr<Command>>>
46public:
47 using allocator_type = Allocator;
48
49 /**
50 * @brief Constructs a WorldCmdBuffer for recording commands.
51 * @param local_storage Reference to system local storage for command execution
52 * @param alloc Allocator instance for internal storage
53 */
54 explicit WorldCmdBuffer(details::SystemLocalStorage& local_storage, Allocator alloc = Allocator{}) noexcept
55 : local_storage_(local_storage), commands_(alloc), alloc_(alloc) {}
56
59
60 /**
61 * @brief Destructor that automatically flushes pending commands.
62 */
64
67
68 /**
69 * @brief Flushes all pending commands to the system local storage.
70 * @details Moves all locally buffered commands to SystemLocalStorage for later execution.
71 * Called automatically by destructor. Safe to call multiple times.
72 */
73 void Flush() noexcept;
74
75 /**
76 * @brief Pushes a custom command function to be executed on the world.
77 * @tparam F Callable type that accepts World&
78 * @param func Function to execute on the world
79 */
82 void Push(F&& func) {
83 commands_.push_back(std::make_unique<details::FunctionCmd<F>>(std::forward<F>(func)));
84 }
85
86 /**
87 * @brief Enqueues destruction of a single entity.
88 * @warning Triggers assertion in next cases:
89 * - Entity is invalid.
90 * - Entity is not owned by world during command execution.
91 * @param entity Entity to destroy
92 */
93 void Destroy(Entity entity);
94
95 /**
96 * @brief Enqueues destruction of entities.
97 * @warning Triggers assertion in next cases:
98 * - Any entity is invalid.
99 * - Any entity is not owned by world during command execution.
100 * @tparam R Range type containing Entity elements
101 * @param entities Entities to destroy
102 */
103 template <std::ranges::range R>
104 requires std::same_as<std::ranges::range_value_t<R>, Entity>
105 void Destroy(const R& entities);
106
107 /**
108 * @brief Enqueues try-destruction of a single entity.
109 * @details Skips non-existing entity.
110 * @warning Triggers assertion in next cases:
111 * - Entity is invalid.
112 * - Entity is not owned by world during command execution.
113 * @param entity Entity to try destroy
114 */
115 void TryDestroy(Entity entity);
116
117 /**
118 * @brief Enqueues try-destruction of entities.
119 * @details Skips non-existing entities.
120 * @warning Triggers assertion in next cases:
121 * - Any entity is invalid.
122 * - Any entity is not owned by world during command execution.
123 * @tparam R Range type containing Entity elements
124 * @param entities Entities to try destroy
125 */
126 template <std::ranges::range R>
127 requires std::same_as<std::ranges::range_value_t<R>, Entity>
128 void TryDestroy(const R& entities);
129
130 /**
131 * @brief Queues a command to clear all events of a specific type.
132 * @tparam T Event type to clear
133 */
134 template <EventTrait T>
135 void ClearEvents() {
136 commands_.push_back(std::make_unique<details::ClearEventsCmd<T>>());
137 }
138
139 /**
140 * @brief Queues a command to clear all event queues without removing registration.
141 * @details Events can still be written/read after this command executes.
142 */
143 void ClearEvents() { commands_.push_back(std::make_unique<details::ClearAllEventsCmd>()); }
144
145 /**
146 * @brief Checks if there are no pending commands.
147 * @return True if no commands are buffered, false otherwise
148 */
149 [[nodiscard]] bool Empty() const noexcept { return commands_.empty(); }
150
151 /**
152 * @brief Gets the number of pending commands.
153 * @return Number of commands in the buffer
154 */
155 [[nodiscard]] size_t Size() const noexcept { return commands_.size(); }
156
157 /**
158 * @brief Gets the allocator used by this buffer.
159 * @return Copy of the allocator
160 */
162
163private:
164 details::SystemLocalStorage& local_storage_; ///< Reference to system local storage
165 std::vector<std::unique_ptr<Command>, Allocator> commands_; ///< Local command buffer
166 [[no_unique_address]] Allocator alloc_; ///< Allocator instance
167};
168
169template <typename Allocator>
171 for (auto& cmd : commands_) {
172 if (cmd != nullptr) [[likely]] {
173 local_storage_.AddCommand(std::move(cmd));
174 }
175 }
176 commands_.clear();
177}
178
179template <typename Allocator>
181 HELIOS_ASSERT(entity.Valid(), "Failed to destroy entity: Entity is not valid!");
182 commands_.push_back(std::make_unique<details::DestroyEntityCmd>(entity));
183}
184
185template <typename Allocator>
186template <std::ranges::range R>
187 requires std::same_as<std::ranges::range_value_t<R>, Entity>
189 HELIOS_ASSERT(std::ranges::all_of(entities, [](const auto& entity) { return entity.Valid(); }),
190 "Failed to destroy entities: All entities must be valid!");
191 commands_.push_back(std::make_unique<details::DestroyEntitiesCmd>(entities));
192}
193
194template <typename Allocator>
196 HELIOS_ASSERT(entity.Valid(), "Failed to try destroy entity: Entity is not valid!");
197 commands_.push_back(std::make_unique<details::TryDestroyEntityCmd>(entity));
198}
199
200template <typename Allocator>
201template <std::ranges::range R>
202 requires std::same_as<std::ranges::range_value_t<R>, Entity>
204 HELIOS_ASSERT(std::ranges::all_of(entities, [](const auto& entity) { return entity.Valid(); }),
205 "Failed to destroy entities: All entities must be valid!");
206 commands_.push_back(std::make_unique<details::TryDestroyEntitiesCmd>(entities));
207}
208
209} // namespace helios::ecs
#define HELIOS_ASSERT(condition,...)
Assertion macro that aborts execution in debug builds.
Definition assert.hpp:140
Unique identifier for entities with generation counter to handle recycling.
Definition entity.hpp:21
constexpr bool Valid() const noexcept
Checks if the entity is valid.
Definition entity.hpp:58
void ClearEvents()
Queues a command to clear all event queues without removing registration.
bool Empty() const noexcept
Checks if there are no pending commands.
allocator_type get_allocator() const noexcept
Gets the allocator used by this buffer.
WorldCmdBuffer & operator=(const WorldCmdBuffer &)=delete
void Push(F &&func)
Pushes a custom command function to be executed on the world.
WorldCmdBuffer(WorldCmdBuffer &&) noexcept=default
WorldCmdBuffer(const WorldCmdBuffer &)=delete
WorldCmdBuffer(details::SystemLocalStorage &local_storage, Allocator alloc=Allocator{}) noexcept
Constructs a WorldCmdBuffer for recording commands.
void TryDestroy(Entity entity)
Enqueues try-destruction of a single entity.
WorldCmdBuffer & operator=(WorldCmdBuffer &&) noexcept=default
void ClearEvents()
Queues a command to clear all events of a specific type.
size_t Size() const noexcept
Gets the number of pending commands.
void Destroy(Entity entity)
Enqueues destruction of a single entity.
void Flush() noexcept
Flushes all pending commands to the system local storage.
The World class manages entities with their components and systems.
Definition world.hpp:53
Command to clear all events of a specific type from the queue.
Definition commands.hpp:751
Command that executes a function with World reference.
Definition commands.hpp:32
Local storage for system-specific data (commands, events, and temporary allocations).
BasicQuery< World, Allocator, Components... > Query
Type alias for query with mutable world access.
Definition query.hpp:2481
STL namespace.