Helios Engine 0.1.0
A modular ECS based data-oriented C++23 game engine
 
Loading...
Searching...
No Matches
sub_app.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/core_pch.hpp>
4
12#include <helios/core/core.hpp>
19
20#include <atomic>
21#include <concepts>
22#include <cstddef>
23#include <functional>
24#include <string_view>
25#include <type_traits>
26#include <utility>
27
28namespace helios::app {
29
30// Forward declarations
31template <ScheduleTrait Schedule, ecs::SystemTrait... Systems>
32 requires(sizeof...(Systems) > 0 && utils::UniqueTypes<Systems...>)
33class SystemConfig;
34
35template <ScheduleTrait Schedule, SystemSetTrait Set>
36class SystemSetConfig;
37
38/**
39 * @brief Trait to identify valid sub-app types.
40 * @details A valid sub-app type must be an empty struct or class.
41 */
42template <typename T>
43concept SubAppTrait = std::is_empty_v<std::remove_cvref_t<T>>;
44
45/**
46 * @brief Trait to identify sub-apps with custom names.
47 * @details A sub-app with name trait must satisfy SubAppTrait and provide:
48 * - `static constexpr std::string_view GetName() noexcept`
49 */
50template <typename T>
51concept SubAppWithNameTrait = SubAppTrait<T> && requires {
52 { T::GetName() } -> std::same_as<std::string_view>;
53};
54
55/**
56 * @brief Trait to identify sub-apps that support async/overlapping updates.
57 * @details A sub-app with async trait must satisfy SubAppTrait and provide:
58 * - `static constexpr bool AllowOverlappingUpdates() noexcept`
59 *
60 * When true, the sub-app can be updated concurrently with other sub-apps.
61 * When false (default), sub-app updates are serialized.
62 * @tparam T Sub-app type
63 *
64 * @example
65 * @code
66 * struct RenderSubApp {
67 * static constexpr bool AllowOverlappingUpdates() noexcept { return true; }
68 * };
69 * @endcode
70 */
71template <typename T>
72concept SubAppWithAsyncTrait = SubAppTrait<T> && requires {
73 { T::AllowOverlappingUpdates() } -> std::same_as<bool>;
74};
75
76/**
77 * @brief Trait to identify sub-apps with maximum overlapping updates.
78 * @details A sub-app with max overlapping updates trait must satisfy SubAppTrait and provide:
79 * - `static constexpr size_t GetMaxOverlappingUpdates() noexcept`
80 *
81 * This is useful for sub-apps like renderers that need to limit concurrent updates
82 * (e.g., max frames in flight).
83 * @tparam T Sub-app type
84 *
85 * @example
86 * @code
87 * struct RenderSubApp {
88 * static constexpr size_t GetMaxOverlappingUpdates() noexcept { return 3; }
89 * };
90 * @endcode
91 */
92template <typename T>
94 { T::GetMaxOverlappingUpdates() } -> std::same_as<size_t>;
95};
96
97/**
98 * @brief Gets whether a sub-app allows overlapping updates.
99 * @tparam T Sub-app type
100 * @return True if overlapping updates are allowed, false otherwise
101 */
102template <SubAppTrait T>
103constexpr bool SubAppAllowsOverlappingUpdates() noexcept {
104 if constexpr (SubAppWithAsyncTrait<T>) {
105 return T::AllowOverlappingUpdates();
106 } else {
107 return false; // Default: no overlapping updates
108 }
109}
110
111/**
112 * @brief Gets the maximum number of overlapping updates for a sub-app.
113 * @tparam T Sub-app type
114 * @return Maximum overlapping updates, or 0 if not specified
115 */
116template <SubAppTrait T>
117constexpr size_t SubAppMaxOverlappingUpdates() noexcept {
119 return T::GetMaxOverlappingUpdates();
120 } else {
121 return 0; // Default: no limit
122 }
123}
124
125/**
126 * @brief Type alias for sub-app type IDs.
127 */
128using SubAppTypeId = size_t;
129
130/**
131 * @brief Type alias for module type IDs.
132 * @tparam T Module type
133 * @return Unique type ID for the module
134 */
135template <SubAppTrait T>
136constexpr SubAppTypeId SubAppTypeIdOf() noexcept {
137 return ctti::type_index_of<T>().hash();
138}
139
140/**
141 * @brief Gets the name of a sub-app type.
142 * @tparam T Sub-app type
143 * @return Name of the sub-app
144 */
145template <SubAppTrait T>
146constexpr std::string_view SubAppNameOf() noexcept {
147 if constexpr (SubAppWithNameTrait<T>) {
148 return T::GetName();
149 } else {
150 return ctti::name_of<T>();
151 }
152}
153
154/**
155 * @brief A sub-application with its own ECS world, systems, and resources.
156 * @details SubApp encapsulates an ECS world and manages its own systems and resources.
157 * It allows for modular separation of functionality within an application,
158 * such as having distinct simulation and rendering sub-apps.
159 * Each SubApp can have its own execution schedules and can extract data from a main world if needed.
160 *
161 * SubApps can be added to the main App instance and can be updated independently.
162 * They support adding modules that can register their own systems and resources.
163 *
164 * @note Not thread-safe.
165 * Use AllowOverlappingUpdates() trait for controlled concurrent access.
166 */
167class SubApp {
168public:
169#ifdef HELIOS_MOVEONLY_FUNCTION_AVALIABLE
170 using ExtractFn = std::move_only_function<void(const ecs::World&, ecs::World&)>;
171#else
172 using ExtractFn = std::function<void(const ecs::World&, ecs::World&)>;
173#endif
174
175 SubApp() = default;
176 SubApp(const SubApp&) = delete;
177 SubApp(SubApp&& other) noexcept;
178 ~SubApp() = default;
179
180 SubApp& operator=(const SubApp&) = delete;
181 SubApp& operator=(SubApp&& other) noexcept;
182
183 /**
184 * @brief Clears the sub-app, removing all data.
185 * @warning Triggers assertion if sub app is updating.
186 */
187 void Clear();
188
189 /**
190 * @brief Updates this sub-app by executing all scheduled systems.
191 * @details This method checks the updating flag to prevent concurrent updates when overlapping
192 * updates are not allowed. SubApps with AllowOverlappingUpdates() can bypass this check.
193 * @warning Triggers assertion if scheduler was not built.
194 * @param executor Async executor for parallel execution
195 */
196 void Update(async::Executor& executor);
197
198 /**
199 * @brief Extracts data from the main world into this sub-app.
200 * @warning Triggers assertion if sub app is updating.
201 * @param main_world Const reference to the main world to extract data from
202 */
203 void Extract(const ecs::World& main_world);
204
205 /**
206 * @brief Builds execution graphs for all schedules.
207 * @details Should be called after all systems are added and before first execution.
208 * @warning Triggers assertion if sub app is updating.
209 */
210 void BuildScheduler();
211
212 /**
213 * @brief Executes a specific schedule.
214 * @warning Triggers assertion if scheduler was not built.
215 * @tparam S Schedule type
216 * @param executor Async executor for parallel execution
217 * @param schedule Schedule to execute
218 */
219 template <ScheduleTrait S>
220 void ExecuteSchedule(async::Executor& executor, S schedule = {});
221
222 /**
223 * @brief Executes all schedules in a specific stage.
224 * @warning Triggers assertion if scheduler was not built.
225 * @tparam S Stage type (must satisfy StageTrait)
226 * @param executor Async executor for parallel execution
227 */
228 template <StageTrait S>
229 void ExecuteStage(async::Executor& executor);
230
231 /**
232 * @brief Adds a system to the specified schedule in the sub-app.
233 * @warning Triggers assertion if sub app is updating.
234 * @tparam T System type
235 * @tparam S Schedule type
236 * @param schedule Schedule to add system to
237 */
238 template <ecs::SystemTrait T, ScheduleTrait S>
239 void AddSystem(S schedule = {});
240
241 /**
242 * @brief Adds multiple systems to the specified schedule in the sub-app.
243 * @warning Triggers assertion if sub app is updating.
244 * @tparam Systems System types
245 * @tparam S Schedule type
246 * @param schedule Schedule to add systems to
247 */
248 template <ecs::SystemTrait... Systems, ScheduleTrait S>
249 requires(sizeof...(Systems) > 1 && utils::UniqueTypes<Systems...>)
250 void AddSystems(S schedule = {});
251
252 /**
253 * @brief Adds systems with fluent configuration builder.
254 * @details Returns a builder that allows chaining configuration methods like
255 * .After(), .Before(), .InSet(), and .Sequence().
256 * @warning Triggers assertion if sub app is updating.
257 * @tparam Systems System types to add
258 * @tparam S Schedule type
259 * @param schedule Schedule to add systems to
260 * @return SystemConfig builder for fluent configuration
261 *
262 * @example
263 * @code
264 * sub_app.AddSystemsBuilder<MovementSystem, CollisionSystem>(kUpdate)
265 * .After<InputSystem>()
266 * .Before<RenderSystem>()
267 * .InSet<PhysicsSet>()
268 * .Sequence();
269 * @endcode
270 */
271 template <ecs::SystemTrait... Systems, ScheduleTrait S>
272 requires(sizeof...(Systems) > 0 && utils::UniqueTypes<Systems...>)
273 auto AddSystemsBuilder(S schedule = {}) -> SystemConfig<S, Systems...>;
274
275 /**
276 * @brief Adds a single system with fluent configuration builder.
277 * @details Returns a builder that allows chaining configuration methods.
278 * @warning Triggers assertion if sub app is updating.
279 * @tparam T System type to add
280 * @tparam S Schedule type
281 * @param schedule Schedule to add system to
282 * @return SystemConfig builder for fluent configuration
283 */
284 template <ecs::SystemTrait T, ScheduleTrait S>
285 auto AddSystemBuilder(S schedule = {}) -> SystemConfig<S, T>;
286
287 /**
288 * @brief Configures a system set with fluent builder.
289 * @details Returns a builder that allows configuring set ordering.
290 * @warning Triggers assertion if sub app is updating.
291 * @tparam Set System set type to configure
292 * @tparam S Schedule type
293 * @param schedule Schedule where the set is configured
294 * @return SystemSetConfig builder for fluent configuration
295 *
296 * @example
297 * @code
298 * sub_app.ConfigureSet<PhysicsSet>(kUpdate)
299 * .After<InputSet>()
300 * .Before<RenderSet>();
301 * @endcode
302 */
303 template <SystemSetTrait Set, ScheduleTrait S>
304 auto ConfigureSet(S schedule = {}) -> SystemSetConfig<S, Set>;
305
306 /**
307 * @brief Inserts a resource into the sub-app's world.
308 * @warning Triggers assertion if sub app is updating.
309 * @tparam T Resource type
310 * @param resource Resource to insert
311 */
312 template <ecs::ResourceTrait T>
313 void InsertResource(T&& resource) {
314 world_.InsertResource(std::forward<T>(resource));
315 }
316
317 /**
318 * @brief Emplaces a resource into the sub-app's world.
319 * @warning Triggers assertion if sub app is updating.
320 * @tparam T Resource type
321 * @tparam Args Constructor argument types
322 * @param args Arguments to forward to resource constructor
323 */
324 template <ecs::ResourceTrait T, typename... Args>
325 requires std::constructible_from<T, Args...>
326 void EmplaceResource(Args&&... args) {
327 world_.EmplaceResource<T>(std::forward<Args>(args)...);
328 }
329
330 /**
331 * @brief Registers an event type for use in this sub-app.
332 * @details Events must be registered before they can be written or read.
333 * @warning Triggers assertion if sub app is updating.
334 * @tparam T Event type
335 */
336 template <ecs::EventTrait T>
337 void AddEvent() {
338 world_.AddEvent<T>();
339 }
340
341 /**
342 * @brief Registers multiple event types for use in this sub-app.
343 * @warning Triggers assertion if sub app is updating.
344 * @tparam Events Event types to register
345 */
346 template <ecs::EventTrait... Events>
347 requires(sizeof...(Events) > 1)
348 void AddEvents() {
349 world_.AddEvents<Events...>();
350 }
351
352 /**
353 * @brief Sets custom extraction function for this sub-app.
354 * @details The extraction function is called before the sub-app's Update to copy
355 * data from the main world.
356 * This is useful for example for render sub-app that need to extract transform, mesh,
357 * and camera data from the main simulation world.
358 * @param extract_fn Function that takes main world and sub-app world references
359 */
360 void SetExtractFunction(ExtractFn extract_fn) noexcept { extract_fn_ = std::move(extract_fn); }
361
362 /**
363 * @brief Sets whether this sub-app allows overlapping updates.
364 * @param allow True to allow concurrent updates, false otherwise
365 */
366 void SetAllowOverlappingUpdates(bool allow) noexcept { allow_overlapping_updates_ = allow; }
367
368 /**
369 * @brief Sets the maximum number of overlapping updates.
370 * @param max Maximum number of concurrent updates (0 = unlimited)
371 */
372 void SetMaxOverlappingUpdates(size_t max) noexcept { max_overlapping_updates_ = max; }
373
374 /**
375 * @brief Checks if a system of type T is in any schedule.
376 * @tparam T System type
377 * @return True if system is present, false otherwise
378 */
379 template <ecs::SystemTrait T>
380 [[nodiscard]] bool ContainsSystem() const noexcept {
381 return scheduler_.ContainsSystem<T>();
382 }
383
384 /**
385 * @brief Checks if a system of type T is in the specified schedule.
386 * @tparam T System type
387 * @tparam S Schedule type
388 * @param schedule Schedule to check
389 * @return True if system is present, false otherwise
390 */
391 template <ecs::SystemTrait T, ScheduleTrait S>
392 [[nodiscard]] bool ContainsSystem(S schedule = {}) const noexcept {
393 return scheduler_.ContainsSystem<T>(schedule);
394 }
395
396 /**
397 * @brief Checks if a resource of type T exists in this sub-app.
398 * @tparam T Resource type
399 * @return True if resource exists, false otherwise
400 */
401 template <ecs::ResourceTrait T>
402 [[nodiscard]] bool HasResource() const noexcept {
403 return world_.HasResource<T>();
404 }
405
406 /**
407 * @brief Checks if an event type is registered in this sub-app.
408 * @tparam T Event type
409 * @return True if event type is registered, false otherwise
410 */
411 template <ecs::EventTrait T>
412 [[nodiscard]] bool HasEvent() const noexcept {
413 return world_.HasEvent<T>();
414 }
415
416 /**
417 * @brief Checks if the sub-app is currently updating.
418 * @return True if update is in progress, false otherwise
419 */
420 [[nodiscard]] bool IsUpdating() const noexcept { return is_updating_.load(std::memory_order_acquire); }
421
422 /**
423 * @brief Checks if this sub-app allows overlapping updates.
424 * @return True if overlapping updates are allowed, false otherwise
425 */
426 [[nodiscard]] bool AllowsOverlappingUpdates() const noexcept { return allow_overlapping_updates_; }
427
428 /**
429 * @brief Gets the total number of systems across all schedules.
430 * @return Total number of systems
431 */
432 [[nodiscard]] size_t SystemCount() const noexcept { return scheduler_.SystemCount(); }
433
434 /**
435 * @brief Gets the number of systems in the specified schedule of this sub-app.
436 * @tparam S Schedule type
437 * @param schedule Schedule to query
438 * @return Number of systems in the schedule
439 */
440 template <ScheduleTrait S>
441 [[nodiscard]] size_t SystemCount(S schedule = {}) const noexcept {
442 return scheduler_.SystemCount(schedule);
443 }
444
445 /**
446 * @brief Gets const reference to this sub-app's world.
447 * @return Const reference to the ECS world
448 */
449 [[nodiscard]] const ecs::World& GetWorld() const noexcept { return world_; }
450
451private:
452 /**
453 * @brief Gets mutable reference to this sub-app's world.
454 * @return Reference to the ECS world
455 */
456 [[nodiscard]] ecs::World& GetWorld() noexcept { return world_; }
457
458 /**
459 * @brief Gets mutable reference to the scheduler.
460 * @return Reference to the scheduler
461 */
462 [[nodiscard]] details::Scheduler& GetScheduler() noexcept { return scheduler_; }
463
464 ecs::World world_; ///< The ECS world for this sub-app
465 details::Scheduler scheduler_; ///< Scheduler managing system execution
466
467 /// Optional extraction function for data transfer from main world
468 ExtractFn extract_fn_;
469
470 std::atomic<bool> is_updating_{false}; ///< Flag to track if update is in progress
471 bool graphs_built_ = false; ///< Flag to track if execution graphs are built
472
473 bool allow_overlapping_updates_ = false; ///< Whether concurrent updates are allowed
474 size_t max_overlapping_updates_ = 0; ///< Maximum concurrent updates (0 = unlimited)
475 std::atomic<size_t> current_overlapping_updates_{0}; ///< Current number of overlapping updates
476
477 friend class App;
478
479 template <ScheduleTrait Schedule, ecs::SystemTrait... Systems>
480 requires(sizeof...(Systems) > 0 && utils::UniqueTypes<Systems...>)
481 friend class SystemConfig;
482
483 template <ScheduleTrait Schedule, SystemSetTrait Set>
484 friend class SystemSetConfig;
485};
486
487inline SubApp::SubApp(SubApp&& other) noexcept
488 : world_(std::move(other.world_)),
489 scheduler_(std::move(other.scheduler_)),
490 extract_fn_(std::move(other.extract_fn_)),
491 is_updating_(other.is_updating_.load(std::memory_order_acquire)),
492 graphs_built_(other.graphs_built_),
493 allow_overlapping_updates_(other.allow_overlapping_updates_),
494 max_overlapping_updates_(other.max_overlapping_updates_),
495 current_overlapping_updates_(other.current_overlapping_updates_.load(std::memory_order_acquire)) {}
496
497inline SubApp& SubApp::operator=(SubApp&& other) noexcept {
498 if (this != &other) {
499 world_ = std::move(other.world_);
500 scheduler_ = std::move(other.scheduler_);
501 extract_fn_ = std::move(other.extract_fn_);
502 is_updating_.store(other.is_updating_.load(std::memory_order_acquire), std::memory_order_release);
503 graphs_built_ = other.graphs_built_;
504 allow_overlapping_updates_ = other.allow_overlapping_updates_;
505 max_overlapping_updates_ = other.max_overlapping_updates_;
506 current_overlapping_updates_.store(other.current_overlapping_updates_.load(std::memory_order_acquire),
507 std::memory_order_release);
508 }
509 return *this;
510}
511
512inline void SubApp::Clear() {
513 HELIOS_ASSERT(!IsUpdating(), "Failed to clear sub app: Cannot clear while app is running!");
514
515 world_.Clear();
516 scheduler_.Clear();
517 extract_fn_ = nullptr;
518 graphs_built_ = false;
519}
520
521inline void SubApp::Update(async::Executor& executor) {
522 HELIOS_ASSERT(graphs_built_, "Failed to update sub app: Scheduler must be built before update!");
523
524 if (!allow_overlapping_updates_) {
525 // Enforce single update at a time
526 bool expected = false;
527 if (!is_updating_.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) {
528 HELIOS_ERROR("Failed to update sub app: Overlapping updates not allowed!");
529 return;
530 }
531 } else {
532 // Track overlapping updates if limit is set
533 if (max_overlapping_updates_ > 0) {
534 size_t current = current_overlapping_updates_.fetch_add(1, std::memory_order_acq_rel);
535 if (current >= max_overlapping_updates_) {
536 current_overlapping_updates_.fetch_sub(1, std::memory_order_acq_rel);
537 HELIOS_WARN("Failed to update sub app: Max overlapping updates ({}) reached!", max_overlapping_updates_);
538 return;
539 }
540 }
541
542 is_updating_.store(true, std::memory_order_release);
543 }
544
545 // Execute all stages in order (StartUpStage only runs during Initialize, not Update)
546 scheduler_.ExecuteStage<MainStage>(world_, executor);
547 scheduler_.ExecuteStage<UpdateStage>(world_, executor);
548 scheduler_.ExecuteStage<CleanUpStage>(world_, executor);
549
550 // Merge all deferred commands into world after execution
551 scheduler_.MergeCommandsToWorld(world_);
552
553 // Execute all commands (create entities, add/remove components, etc.)
554 world_.Update();
555
556 // Reset all per-system frame allocators to reclaim temporary memory
557 scheduler_.ResetFrameAllocators();
558
559 // Clear update flags
560 if (allow_overlapping_updates_ && max_overlapping_updates_ > 0) {
561 current_overlapping_updates_.fetch_sub(1, std::memory_order_acq_rel);
562 }
563
564 is_updating_.store(false, std::memory_order_release);
565}
566
567inline void SubApp::Extract(const ecs::World& main_world) {
568 HELIOS_ASSERT(!IsUpdating(), "Failed to extract: Cannot extract while app is running!");
569
570 if (extract_fn_) {
571 extract_fn_(main_world, world_);
572 }
573}
574
576 HELIOS_ASSERT(!IsUpdating(), "Failed to build scheduler: Cannot build while app is running!");
577
578 scheduler_.BuildAllGraphs(world_);
579 graphs_built_ = true;
580}
581
582template <ScheduleTrait S>
583inline void SubApp::ExecuteSchedule(async::Executor& executor, S /*schedule*/) {
584 HELIOS_ASSERT(graphs_built_, "Failed to execute schedule: Scheduler must be built before update!");
585 scheduler_.ExecuteSchedule<S>(world_, executor);
586}
587
588template <StageTrait S>
589inline void SubApp::ExecuteStage(async::Executor& executor) {
590 HELIOS_ASSERT(graphs_built_, "Failed to execute stage: Scheduler must be built before update!");
591 scheduler_.ExecuteStage<S>(world_, executor);
592}
593
594template <ecs::SystemTrait T, ScheduleTrait S>
595inline void SubApp::AddSystem(S schedule) {
596 HELIOS_ASSERT(!IsUpdating(), "Failed to add system '{}': Cannot add systems while app is running!",
598
599 if (ContainsSystem<T>(schedule)) [[unlikely]] {
600 HELIOS_WARN("System '{}' is already exist in app schedule '{}'!", ecs::SystemNameOf<T>(), ScheduleNameOf<S>());
601 return;
602 }
603
604 scheduler_.AddSystem<T>(schedule);
605 graphs_built_ = false;
606}
607
608template <ecs::SystemTrait... Systems, ScheduleTrait S>
609 requires(sizeof...(Systems) > 1 && utils::UniqueTypes<Systems...>)
610inline void SubApp::AddSystems(S schedule) {
611 HELIOS_ASSERT(!IsUpdating(), "Failed to add systems: Cannot add systems while app is running!");
612
613 (scheduler_.AddSystem<Systems>(schedule), ...);
614 graphs_built_ = false;
615}
616
617template <ecs::SystemTrait... Systems, ScheduleTrait S>
618 requires(sizeof...(Systems) > 0 && utils::UniqueTypes<Systems...>)
619inline auto SubApp::AddSystemsBuilder(S schedule) -> SystemConfig<S, Systems...> {
620 HELIOS_ASSERT(!IsUpdating(), "Failed to add systems: Cannot add systems while app is running!");
621 return SystemConfig<S, Systems...>(*this, schedule);
622}
623
624template <ecs::SystemTrait T, ScheduleTrait S>
626 HELIOS_ASSERT(!IsUpdating(), "Failed to add system '{}': Cannot add systems while app is running!",
628 return SystemConfig<S, T>(*this, schedule);
629}
630
631template <SystemSetTrait Set, ScheduleTrait S>
633 HELIOS_ASSERT(!IsUpdating(), "Failed to configure set '{}': Cannot configure sets while app is running!",
634 SystemSetNameOf<Set>());
635 return SystemSetConfig<S, Set>(*this, schedule);
636}
637
638} // namespace helios::app
639
#define HELIOS_ASSERT(condition,...)
Assertion macro that aborts execution in debug builds.
Definition assert.hpp:140
Application class.
Definition app.hpp:97
A sub-application with its own ECS world, systems, and resources.
Definition sub_app.hpp:167
void Clear()
Clears the sub-app, removing all data.
Definition sub_app.hpp:512
const ecs::World & GetWorld() const noexcept
Gets const reference to this sub-app's world.
Definition sub_app.hpp:449
void SetAllowOverlappingUpdates(bool allow) noexcept
Sets whether this sub-app allows overlapping updates.
Definition sub_app.hpp:366
void Update(async::Executor &executor)
Updates this sub-app by executing all scheduled systems.
Definition sub_app.hpp:521
void AddSystem(S schedule={})
Adds a system to the specified schedule in the sub-app.
Definition sub_app.hpp:595
std::function< void(const ecs::World &, ecs::World &)> ExtractFn
Definition sub_app.hpp:172
bool ContainsSystem(S schedule={}) const noexcept
Checks if a system of type T is in the specified schedule.
Definition sub_app.hpp:392
void AddSystems(S schedule={})
Adds multiple systems to the specified schedule in the sub-app.
Definition sub_app.hpp:610
void SetExtractFunction(ExtractFn extract_fn) noexcept
Sets custom extraction function for this sub-app.
Definition sub_app.hpp:360
void BuildScheduler()
Builds execution graphs for all schedules.
Definition sub_app.hpp:575
size_t SystemCount() const noexcept
Gets the total number of systems across all schedules.
Definition sub_app.hpp:432
bool ContainsSystem() const noexcept
Checks if a system of type T is in any schedule.
Definition sub_app.hpp:380
SubApp & operator=(const SubApp &)=delete
auto ConfigureSet(S schedule={}) -> SystemSetConfig< S, Set >
Definition sub_app.hpp:632
size_t SystemCount(S schedule={}) const noexcept
Gets the number of systems in the specified schedule of this sub-app.
Definition sub_app.hpp:441
void Extract(const ecs::World &main_world)
Extracts data from the main world into this sub-app.
Definition sub_app.hpp:567
bool AllowsOverlappingUpdates() const noexcept
Checks if this sub-app allows overlapping updates.
Definition sub_app.hpp:426
void AddEvents()
Registers multiple event types for use in this sub-app.
Definition sub_app.hpp:348
SubApp(const SubApp &)=delete
void ExecuteStage(async::Executor &executor)
Executes all schedules in a specific stage.
Definition sub_app.hpp:589
auto AddSystemBuilder(S schedule={}) -> SystemConfig< S, T >
Adds a single system with fluent configuration builder.
Definition sub_app.hpp:625
void ExecuteSchedule(async::Executor &executor, S schedule={})
Executes a specific schedule.
Definition sub_app.hpp:583
auto AddSystemsBuilder(S schedule={}) -> SystemConfig< S, Systems... >
Definition sub_app.hpp:619
void AddEvent()
Registers an event type for use in this sub-app.
Definition sub_app.hpp:337
void InsertResource(T &&resource)
Inserts a resource into the sub-app's world.
Definition sub_app.hpp:313
bool HasEvent() const noexcept
Checks if an event type is registered in this sub-app.
Definition sub_app.hpp:412
bool HasResource() const noexcept
Checks if a resource of type T exists in this sub-app.
Definition sub_app.hpp:402
void SetMaxOverlappingUpdates(size_t max) noexcept
Sets the maximum number of overlapping updates.
Definition sub_app.hpp:372
bool IsUpdating() const noexcept
Checks if the sub-app is currently updating.
Definition sub_app.hpp:420
void EmplaceResource(Args &&... args)
Emplaces a resource into the sub-app's world.
Definition sub_app.hpp:326
void ExecuteSchedule(ecs::World &world, async::Executor &executor)
Executes all systems in the specified schedule.
bool ContainsSystem() const noexcept
Checks if a system of type T is in any schedule.
void Clear()
Clears all schedules and systems.
void AddSystem(S schedule={})
Adds a system to the specified schedule.
void MergeCommandsToWorld(ecs::World &world)
Merges all system local commands into the world's main command queue.
void BuildAllGraphs(ecs::World &world)
Builds execution graphs for all schedules.
Definition scheduler.cpp:60
void ExecuteStage(ecs::World &world, async::Executor &executor)
Executes all schedules in the specified stage.
size_t SystemCount() const noexcept
Gets the total number of systems across all schedules.
void ResetFrameAllocators() noexcept
Resets all system frame allocators.
Manages worker threads and executes task graphs using work-stealing scheduling.
Definition executor.hpp:33
The World class manages entities with their components and systems.
Definition world.hpp:53
void AddEvents()
Registers multiple event types for use.
Definition world.hpp:451
bool HasEvent() const
Checks if a event registered.
Definition world.hpp:545
void EmplaceResource(Args &&... args)
Emplaces a resource in-place.
Definition world.hpp:352
bool HasResource() const
Checks if a resource exists.
Definition world.hpp:534
void InsertResource(T &&resource)
Inserts a resource into the world.
Definition world.hpp:327
void Clear()
Clears the world, removing all data.
Definition world.hpp:645
void AddEvent()
Registers an event type for use.
Definition world.hpp:967
Trait to identify valid sub-app types.
Definition sub_app.hpp:43
Trait to identify sub-apps with custom names.
Definition sub_app.hpp:51
Trait to identify valid system set types.
Concept for valid event types.
Definition event.hpp:44
Concept for valid resource types.
Definition resource.hpp:21
Concept for valid system types.
Definition system.hpp:76
#define HELIOS_ERROR(...)
Definition logger.hpp:689
#define HELIOS_WARN(...)
Definition logger.hpp:687
constexpr std::string_view SubAppNameOf() noexcept
Gets the name of a sub-app type.
Definition sub_app.hpp:146
size_t SubAppTypeId
Type alias for sub-app type IDs.
Definition sub_app.hpp:128
constexpr SubAppTypeId SubAppTypeIdOf() noexcept
Type alias for module type IDs.
Definition sub_app.hpp:136
constexpr size_t SubAppMaxOverlappingUpdates() noexcept
Gets the maximum number of overlapping updates for a sub-app.
Definition sub_app.hpp:117
constexpr bool SubAppAllowsOverlappingUpdates() noexcept
Gets whether a sub-app allows overlapping updates.
Definition sub_app.hpp:103
STL namespace.
CleanUpStage - cleanup/shutdown phase.
Definition schedules.hpp:64
MainStage - main thread execution phase.
Definition schedules.hpp:39
UpdateStage - main update logic phase.
Definition schedules.hpp:51
Update schedule - main update logic.