Helios Engine 0.1.0
A modular ECS based data-oriented C++23 game engine
 
Loading...
Searching...
No Matches
command_queue.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/core_pch.hpp>
4
8
9#include <algorithm>
10#include <concepts>
11#include <cstddef>
12#include <memory>
13#include <ranges>
14#include <utility>
15#include <vector>
16
17namespace helios::ecs::details {
18
19/**
20 * @brief Command queue for deferred ECS operations.
21 * @details Provides a queue for commands that will be executed during World::Update().
22 * Commands are executed in the order they were enqueued, ensuring predictable behavior.
23 *
24 * Features:
25 * - Simple vector-based implementation for main thread usage
26 * - Bulk operations for better performance
27 * - Type-safe command emplacement
28 *
29 * @note Not thread-safe.
30 * All operations must be performed on the main thread.
31 */
32class CmdQueue {
33public:
34 CmdQueue() = default;
35 CmdQueue(const CmdQueue&) = delete;
38
41
42 /**
43 * @brief Clears all pending commands from the queue.
44 * @details Removes all commands currently in the queue.
45 */
46 void Clear() noexcept { commands_.clear(); }
47
48 /**
49 * @brief Reserves capacity for commands.
50 * @details Pre-allocates memory to avoid reallocations during enqueue operations.
51 * @param capacity Number of commands to reserve space for
52 */
53 void Reserve(size_t capacity) { commands_.reserve(capacity); }
54
55 /**
56 * @brief Constructs and enqueues a command in-place.
57 * @details Creates a command of type T by forwarding arguments to its constructor.
58 * @tparam T Command type that derives from Command
59 * @tparam Args Argument types for T's constructor
60 * @param args Arguments to forward to T's constructor
61 */
62 template <CommandTrait T, typename... Args>
63 requires std::constructible_from<T, Args...>
64 void Emplace(Args&&... args) {
65 commands_.push_back(std::make_unique<T>(std::forward<Args>(args)...));
66 }
67
68 /**
69 * @brief Enqueues a pre-constructed command.
70 * @details Adds an already constructed command to the queue.
71 * @warning Triggers assertion if command is nullptr.
72 * @param command Unique pointer to command to enqueue
73 */
74 void Enqueue(std::unique_ptr<Command> command);
75
76 /**
77 * @brief Enqueues multiple commands in bulk.
78 * @details Efficiently enqueues a range of commands in a single operation.
79 * The range is consumed (moved from) during this operation.
80 * @warning Triggers assertion if any command in range is nullptr.
81 * @tparam R Range type containing unique_ptr<Command> elements
82 * @param commands Range of commands to enqueue (will be moved from)
83 */
84 template <std::ranges::range R>
85 requires std::same_as<std::ranges::range_value_t<R>, std::unique_ptr<Command>>
86 void EnqueueBulk(R&& commands);
87
88 /**
89 * @brief Gets all commands and clears the queue.
90 * @details Moves all commands out of the queue, leaving it empty.
91 * @return Vector containing all commands that were in the queue
92 */
93 [[nodiscard]] auto DequeueAll() noexcept -> std::vector<std::unique_ptr<Command>> {
94 return std::exchange(commands_, {});
95 }
96
97 /**
98 * @brief Checks if the queue is empty.
99 * @details Returns true if there are no commands in the queue.
100 * @return True if queue is empty, false otherwise
101 */
102 [[nodiscard]] bool Empty() const noexcept { return commands_.empty(); }
103
104 /**
105 * @brief Gets the number of commands in the queue.
106 * @details Returns the exact size of the queue.
107 * @return Number of commands in queue
108 */
109 [[nodiscard]] size_t Size() const noexcept { return commands_.size(); }
110
111private:
112 std::vector<std::unique_ptr<Command>> commands_; ///< Vector storing command pointers
113};
114
115inline void CmdQueue::Enqueue(std::unique_ptr<Command> command) {
116 HELIOS_ASSERT(command != nullptr, "Failed to enqueue command: command is nullptr!");
117 commands_.push_back(std::move(command));
118}
119
120template <std::ranges::range R>
121 requires std::same_as<std::ranges::range_value_t<R>, std::unique_ptr<Command>>
123 if constexpr (std::ranges::sized_range<R>) {
124 // Reserve space to avoid multiple reallocations
125 commands_.reserve(commands_.size() + std::ranges::size(commands));
126 }
127
128 // Move all commands into the queue
129 for (auto&& command : commands) {
130 HELIOS_ASSERT(command != nullptr, "Failed to enqueue commands in bulk: one of the commands is nullptr!");
131 commands_.push_back(std::move(command));
132 }
133}
134
135} // 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
Command queue for deferred ECS operations.
void EnqueueBulk(R &&commands)
Enqueues multiple commands in bulk.
CmdQueue(CmdQueue &&) noexcept=default
bool Empty() const noexcept
Checks if the queue is empty.
void Emplace(Args &&... args)
Constructs and enqueues a command in-place.
void Reserve(size_t capacity)
Reserves capacity for commands.
auto DequeueAll() noexcept -> std::vector< std::unique_ptr< Command > >
Gets all commands and clears the queue.
size_t Size() const noexcept
Gets the number of commands in the queue.
CmdQueue(const CmdQueue &)=delete
void Clear() noexcept
Clears all pending commands from the queue.
void Enqueue(std::unique_ptr< Command > command)
Enqueues a pre-constructed command.
BasicQuery< World, Allocator, Components... > Query
Type alias for query with mutable world access.
Definition query.hpp:2481
STL namespace.