Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
queue.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <helios/ecs/details/profile.hpp>
6
7#include <cstddef>
8#include <memory_resource>
9#include <ranges>
10
11namespace helios::ecs {
12
13class World;
14
15/**
16 * @brief Command queue for deferred ECS operations.
17 * @details Provides a queue for commands that will be executed during
18 * `World::Update()`.
19 * Commands are executed in the order they were enqueued, ensuring predictable
20 * behavior.
21 * @note Not thread-safe.
22 * @tparam Allocator Allocator type for command storage (default:
23 * `std::allocator<std::byte>`)
24 */
25template <typename Allocator = std::allocator<std::byte>>
26class CmdQueue {
27private:
28 using CommandStorage =
29 container::CallableBufferArray<Allocator, void(World&)>;
30
31public:
32 using size_type = CommandStorage::size_type;
33 using allocator_type = CommandStorage::allocator_type;
34
35 /**
36 * @brief Constructs a command queue with a custom allocator.
37 * @param allocator Allocator instance
38 */
39 explicit constexpr CmdQueue(allocator_type allocator = allocator_type{})
40 : commands_(std::move(allocator)) {}
41
42 /**
43 * @brief Constructs a command queue from a PMR memory resource.
44 * @details Enabled only when `allocator_type` is constructible from
45 * `std::pmr::memory_resource*`.
46 * @param resource Memory resource used to construct allocator
47 */
48 explicit constexpr CmdQueue(std::pmr::memory_resource* resource)
49 requires std::constructible_from<allocator_type, std::pmr::memory_resource*>
50 : CmdQueue(allocator_type{resource}) {}
51
52 CmdQueue(std::nullptr_t) = delete;
53
54 CmdQueue(const CmdQueue&) = delete;
55 constexpr CmdQueue(CmdQueue&&) noexcept = default;
56 ~CmdQueue() = default;
57
58 CmdQueue& operator=(const CmdQueue&) = delete;
59 CmdQueue& operator=(CmdQueue&&) noexcept = default;
60
61 /**
62 * @brief Clears all pending commands from the queue.
63 * @details Removes all commands currently in the queue.
64 */
65 void Clear() noexcept { commands_.Clear(); }
66
67 /**
68 * @brief Reserves capacity for commands.
69 * @details Pre-allocates memory to avoid reallocations during enqueue
70 * operations.
71 * @param capacity Number of commands to reserve space for
72 */
73 constexpr void Reserve(size_type capacity) { commands_.Reserve(capacity); }
74
75 /**
76 * @brief Merges another queue into this one by moving its commands.
77 * @details Moves all commands from the other queue into this one.
78 * @param other Queue to merge
79 */
80 constexpr void Merge(CmdQueue&& other) {
81 commands_.Merge(std::move(other.commands_));
82 }
83
84 /**
85 * @brief Enqueues a command by moving it into the queue.
86 * @details Moves a command into the queue.
87 * @tparam T Command type
88 * @param command Command to enqueue
89 */
90 template <CommandTrait T>
91 void Enqueue(T&& command);
92
93 /**
94 * @brief Enqueues multiple commands in bulk.
95 * @details Moves a range of commands into the queue in a single operation.
96 * @tparam R Range type
97 * @param commands Range of commands to enqueue
98 */
99 template <std::ranges::input_range R>
101 void EnqueueBulk(R&& commands);
102
103 /**
104 * @brief Executes all commands in the queue and clears the queue.
105 * @param world Reference to the World instance
106 */
107 void ExecuteAll(World& world);
108
109 /**
110 * @brief Checks if the queue is empty.
111 * @return True if queue is empty, false otherwise
112 */
113 [[nodiscard]] constexpr bool Empty() const noexcept {
114 return commands_.Empty();
115 }
116
117 /**
118 * @brief Gets the number of commands in the queue.
119 * @return Number of commands in queue
120 */
121 [[nodiscard]] constexpr size_type Size() const noexcept {
122 return commands_.Size();
123 }
124
125 /**
126 * @brief Gets the allocator used by the command storage.
127 * @return Allocator instance
128 */
129 [[nodiscard]] constexpr allocator_type GetAllocator() const {
130 return commands_.GetAllocator();
131 }
132
133private:
134 CommandStorage commands_; ///< Container storing commands
135};
136
137template <typename Allocator>
138template <CommandTrait T>
139inline void CmdQueue<Allocator>::Enqueue(T&& command) {
140 using DecayedT = std::remove_cvref_t<T>;
141 commands_.template Push<&DecayedT::Execute>(std::forward<T>(command));
142}
143
144template <typename Allocator>
145template <std::ranges::input_range R>
147inline void CmdQueue<Allocator>::EnqueueBulk(R&& commands) {
148 if constexpr (std::ranges::sized_range<R>) {
149 commands_.Reserve(commands_.Size() + std::ranges::size(commands));
150 }
151
152 for (auto&& cmd : std::forward<R>(commands)) {
153 Enqueue(std::forward<decltype(cmd)>(cmd));
154 }
155}
156
157template <typename Allocator>
159 HELIOS_ECS_PROFILE_SCOPE_N("helios::ecs::CmdQueue::ExecuteAll");
160 HELIOS_ECS_PROFILE_ZONE_VALUE(commands_.Size());
161 commands_.Invoke(world);
162 Clear();
163}
164
165/**
166 * @brief Command queue for deferred ECS operations that uses a polymorphic
167 * allocator.
168 * @details Provides a queue for commands that will be executed during
169 * `World::Update()`.
170 * Commands are executed in the order they were enqueued, ensuring predictable
171 * behavior.
172 * @note Not thread-safe.
173 */
175
176} // namespace helios::ecs
Command queue for deferred ECS operations.
Definition queue.hpp:26
CmdQueue(std::nullptr_t)=delete
CommandStorage::size_type size_type
Definition queue.hpp:32
CmdQueue(const CmdQueue &)=delete
void Enqueue(T &&command)
Enqueues a command by moving it into the queue.
Definition queue.hpp:139
CommandStorage::allocator_type allocator_type
Definition queue.hpp:33
void EnqueueBulk(R &&commands)
Enqueues multiple commands in bulk.
Definition queue.hpp:147
constexpr void Reserve(size_type capacity)
Reserves capacity for commands.
Definition queue.hpp:73
constexpr bool Empty() const noexcept
Checks if the queue is empty.
Definition queue.hpp:113
constexpr CmdQueue(CmdQueue &&) noexcept=default
constexpr CmdQueue(allocator_type allocator=allocator_type{})
Constructs a command queue with a custom allocator.
Definition queue.hpp:39
void ExecuteAll(World &world)
Executes all commands in the queue and clears the queue.
Definition queue.hpp:158
void Clear() noexcept
Definition queue.hpp:65
constexpr allocator_type GetAllocator() const
Gets the allocator used by the command storage.
Definition queue.hpp:129
constexpr size_type Size() const noexcept
Gets the number of commands in the queue.
Definition queue.hpp:121
constexpr CmdQueue(std::pmr::memory_resource *resource)
Constructs a command queue from a PMR memory resource.
Definition queue.hpp:48
constexpr void Merge(CmdQueue &&other)
Merges another queue into this one by moving its commands.
Definition queue.hpp:80
The World class manages entities with their components and systems.
Definition world.hpp:39
Concept that defines the requirements for a command trait.
Definition command.hpp:18
typename details::CallableBufferArrayDeducer< Args... >::type CallableBufferArray
Inline storage for heterogeneous callable instances with type-erased invocation.
CmdQueue< std::pmr::polymorphic_allocator< std::byte > > PmrCmdQueue
Command queue for deferred ECS operations that uses a polymorphic allocator.
Definition queue.hpp:174
STL namespace.