Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
world_buffer.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <concepts>
9#include <memory_resource>
10#include <type_traits>
11
12namespace helios::ecs {
13
14/**
15 * @brief Command buffer for deferred `World` operations.
16 * @details Collects commands and then pushes them into a queue.
17 * Commands are enqueued in the order they were added, ensuring predictable
18 * behavior.
19 * @note Not thread-safe.
20 * @tparam Allocator Allocator type for command storage (default:
21 * `std::allocator<std::byte>`)
22 */
23template <typename Allocator = std::allocator<std::byte>>
25public:
28
29 /**
30 * @brief Constructs a world command buffer with a custom allocator.
31 * @param queue Queue to push commands into
32 * @param allocator Allocator instance
33 */
34 explicit constexpr WorldCmdBuffer(CmdQueue<Allocator>& queue,
35 allocator_type allocator = allocator_type{})
36 : commands_(allocator), queue_(queue) {}
37
38 /**
39 * @brief Constructs a world command buffer from a PMR memory resource.
40 * @details Enabled only when `allocator_type` is constructible from
41 * `std::pmr::memory_resource*`.
42 * @param queue Queue to push commands into
43 * @param resource Memory resource used to construct allocator
44 */
46 std::pmr::memory_resource* resource)
47 requires std::constructible_from<allocator_type, std::pmr::memory_resource*>
48 : WorldCmdBuffer(queue, allocator_type{resource}) {}
49
50 WorldCmdBuffer(CmdQueue<Allocator>& queue, std::nullptr_t) = delete;
51
54 constexpr ~WorldCmdBuffer() { queue_.Merge(std::move(commands_)); }
55
58
59 /**
60 * @brief Clears all pending commands from the buffer.
61 * @details Removes all commands currently in the buffer.
62 */
63 void Clear() noexcept { commands_.Clear(); }
64
65 /**
66 * @brief Reserves capacity for commands.
67 * @details Pre-allocates memory to avoid reallocations during enqueue
68 * operations.
69 * @param capacity Number of commands to reserve space for
70 */
71 constexpr void Reserve(size_type capacity) { commands_.Reserve(capacity); }
72
73 /**
74 * @brief Enqueues a command to insert a resource into the world.
75 * @details Replaces existing resource if present.
76 * @note Not thread-safe.
77 * @tparam T Resource type
78 * @param resource Resource to insert
79 */
80 template <ResourceTrait T>
81 auto InsertResource(this auto&& self, T&& resource)
82 -> decltype(std::forward<decltype(self)>(self));
83
84 /**
85 * @brief Enqueues a command to try to insert a resource if not present.
86 * @note Not thread-safe.
87 * @tparam T Resource type
88 * @param resource Resource to insert
89 */
90 template <ResourceTrait T>
91 auto TryInsertResource(this auto&& self, T&& resource)
92 -> decltype(std::forward<decltype(self)>(self));
93
94 /**
95 * @brief Enqueues a command to remove a resource from the world.
96 * @note Not thread-safe.
97 * @warning Triggers assertion if resource does not exist.
98 * @tparam T Resource type
99 */
100 template <ResourceTrait T>
101 auto RemoveResource(this auto&& self)
102 -> decltype(std::forward<decltype(self)>(self));
103
104 /**
105 * @brief Enqueues a command to try to remove a resource.
106 * @note Not thread-safe.
107 * @tparam T Resource type
108 */
109 template <ResourceTrait T>
110 auto TryRemoveResource(this auto&& self)
111 -> decltype(std::forward<decltype(self)>(self));
112
113 /**
114 * @brief Enqueues a command to be executed during the next `World::Update()`.
115 * @details Equivalent to enqueueing a `FunctionCmd` with the given callable.
116 * @note Not thread-safe.
117 * @tparam F Callable type, must have signature `void(World&)`
118 * @param command Command to enqueue
119 */
120 template <typename F>
121 requires std::invocable<F, World&>
122 auto DeferredUpdate(this auto&& self, F&& command)
123 -> decltype(std::forward<decltype(self)>(self));
124
125 /**
126 * @brief Checks if the buffer is empty.
127 * @return True if buffer is empty, false otherwise
128 */
129 [[nodiscard]] constexpr bool Empty() const noexcept {
130 return commands_.Empty();
131 }
132
133 /**
134 * @brief Gets the number of commands in the buffer.
135 * @return Number of commands in buffer
136 */
137 [[nodiscard]] constexpr size_type Size() const noexcept {
138 return commands_.Size();
139 }
140
141 /**
142 * @brief Gets the allocator used by the command storage.
143 * @return Allocator instance
144 */
145 [[nodiscard]] constexpr allocator_type GetAllocator() const
146 noexcept(std::is_nothrow_copy_constructible_v<allocator_type>) {
147 return commands_.GetAllocator();
148 }
149
150private:
151 CmdQueue<Allocator> commands_;
152 CmdQueue<Allocator>& queue_;
153};
154
155template <typename Allocator>
156template <ResourceTrait T>
157inline auto WorldCmdBuffer<Allocator>::InsertResource(this auto&& self,
158 T&& resource)
159 -> decltype(std::forward<decltype(self)>(self)) {
160 self.commands_.Enqueue(InsertResourceCmd<T>(std::forward<T>(resource)));
161 return std::forward<decltype(self)>(self);
162}
163
164template <typename Allocator>
165template <ResourceTrait T>
167 T&& resource)
168 -> decltype(std::forward<decltype(self)>(self)) {
169 self.commands_.Enqueue(TryInsertResourceCmd<T>(std::forward<T>(resource)));
170 return std::forward<decltype(self)>(self);
171}
172
173template <typename Allocator>
174template <ResourceTrait T>
175inline auto WorldCmdBuffer<Allocator>::RemoveResource(this auto&& self)
176 -> decltype(std::forward<decltype(self)>(self)) {
177 self.commands_.Enqueue(RemoveResourceCmd<T>());
178 return std::forward<decltype(self)>(self);
179}
180
181template <typename Allocator>
182template <ResourceTrait T>
184 -> decltype(std::forward<decltype(self)>(self)) {
185 self.commands_.Enqueue(TryRemoveResourceCmd<T>());
186 return std::forward<decltype(self)>(self);
187}
188
189template <typename Allocator>
190template <typename F>
191 requires std::invocable<F, World&>
192inline auto WorldCmdBuffer<Allocator>::DeferredUpdate(this auto&& self,
193 F&& command)
194 -> decltype(std::forward<decltype(self)>(self)) {
195 self.commands_.Enqueue(FunctionCmd(std::forward<F>(command)));
196 return std::forward<decltype(self)>(self);
197}
198
199/**
200 * @brief Command buffer for deferred `World` operations that uses a
201 * polymorphic allocator.
202 * @details Collects commands and then pushes them into a queue.
203 * Commands are enqueued in the order they were added, ensuring predictable
204 * behavior.
205 * @note Not thread-safe.
206 * @tparam Allocator Allocator type for command storage (default:
207 * `std::allocator<std::byte>`)
208 */
211
212} // namespace helios::ecs
Command queue for deferred ECS operations.
Definition queue.hpp:26
CommandStorage::size_type size_type
Definition queue.hpp:32
CommandStorage::allocator_type allocator_type
Definition queue.hpp:33
Command to insert a resource into the world.
Command to try insert a resource (only if missing).
Command buffer for deferred World operations.
constexpr void Reserve(size_type capacity)
Reserves capacity for commands.
WorldCmdBuffer & operator=(WorldCmdBuffer &&)=delete
auto InsertResource(this auto &&self, T &&resource) -> decltype(std::forward< decltype(self)>(self))
Enqueues a command to insert a resource into the world.
WorldCmdBuffer(CmdQueue< Allocator > &queue, std::nullptr_t)=delete
auto TryRemoveResource(this auto &&self) -> decltype(std::forward< decltype(self)>(self))
Enqueues a command to try to remove a resource.
constexpr WorldCmdBuffer(CmdQueue< Allocator > &queue, allocator_type allocator=allocator_type{})
Constructs a world command buffer with a custom allocator.
WorldCmdBuffer & operator=(const WorldCmdBuffer &)=delete
auto TryInsertResource(this auto &&self, T &&resource) -> decltype(std::forward< decltype(self)>(self))
Enqueues a command to try to insert a resource if not present.
auto RemoveResource(this auto &&self) -> decltype(std::forward< decltype(self)>(self))
Enqueues a command to remove a resource from the world.
void Clear() noexcept
Clears all pending commands from the buffer.
WorldCmdBuffer(const WorldCmdBuffer &)=delete
WorldCmdBuffer(WorldCmdBuffer &&)=delete
constexpr WorldCmdBuffer(CmdQueue< Allocator > &queue, std::pmr::memory_resource *resource)
Constructs a world command buffer from a PMR memory resource.
constexpr bool Empty() const noexcept
Checks if the buffer is empty.
CmdQueue< Allocator >::size_type size_type
CmdQueue< Allocator >::allocator_type allocator_type
constexpr size_type Size() const noexcept
Gets the number of commands in the buffer.
constexpr allocator_type GetAllocator() const noexcept(std::is_nothrow_copy_constructible_v< allocator_type >)
Gets the allocator used by the command storage.
auto DeferredUpdate(this auto &&self, F &&command) -> decltype(std::forward< decltype(self)>(self))
Enqueues a command to be executed during the next World::Update().
FunctionCmd(G &&) -> FunctionCmd< std::remove_cvref_t< G > >
WorldCmdBuffer< std::pmr::polymorphic_allocator< std::byte > > PmrWorldCmdBuffer
Command buffer for deferred World operations that uses a polymorphic allocator.
STL namespace.
Command to remove resource from the world.
Command to try remove resource (only if present).