Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
app Directory Reference

Directories

 
include
 
src

Detailed Description

`app` — Application Framework

High-level application layer that wires together the ECS, async executor, plugins, and frame scheduling. Owns the main game loop, builtin schedules, and optional sub-apps for parallel or background worlds.

Public API

Type / Function Purpose
App Central owner: executor, scheduler, main sub-app, plugins, sub-apps.
SubApp Independent ECS world + scheduler; supports blocking, overlapping, or async update modes.
Scheduler Frame orchestrator: startup, update, extract, shutdown stages.
Plugin Static plugin base (Build, Finish, Destroy, Poll, IsReady).
DynamicPlugin Runtime-loaded plugin wrapper around a shared library.
ExitCode kSuccess, kFailure.
AppExit Message that requests application shutdown (kManual clear policy).
RunDefault Runner: loop Update() until AppExit.
RunFixed Fixed-timestep runner via FixedRunnerConfig.
RunOnce Single-frame runner.
RunDefaultSubApp Default async sub-app runner.

Builtin Stages & Schedules (schedules.hpp)

Stage Schedules
kStartupStage kMainStartup, kPreStartup, kStartup, kPostStartup
kUpdateStage kFirst, kPreUpdate, kUpdate, kPostUpdate, kLast
kExtractStage kExtract
kShutdownStage kPreShutdown, kShutdown, kPostShutdown

Stages are grouping namespaces only — they are never run directly. Call RegisterBuiltinSchedules(scheduler) to wire default ordering and executor kinds.

Sub-App Label Traits

struct PhysicsLabel {}; // default: blocking
struct AsyncSimLabel {
static constexpr bool kAsync = true;
};
struct OverlapLabel {
static constexpr bool kAllowOverlappingUpdates = true;
static constexpr size_t kMaxOverlappingUpdates = 2; // 0 = unlimited skips
};

Async and overlapping modes are mutually exclusive (compile-time enforced).

Quick Start

struct Position { float x = 0, y = 0; };
struct Velocity { float dx = 1, dy = 0; };
struct MoveEntities {
movables.ForEach([](Position& pos, const Velocity& vel) {
pos.x += vel.dx;
pos.y += vel.dy;
});
}
};
struct RequestExit {
}
};
int main() {
app.AddSystems(helios::app::kUpdate, MoveEntities{}, RequestExit{})
.Sequence();
app.InsertResources(/* resources... */);
return static_cast<int>(app.Run());
}
Application class.
auto AddMessages(this auto &&self) -> decltype(std::forward< decltype(self)>(self))
Registers multiple message types on the main world.
auto InsertResources(this auto &&self, Ts &&... resources) -> decltype(std::forward< decltype(self)>(self))
Inserts or replaces resources in the main world.
ecs::SystemGroupHandle AddSystems(const L &label, Systems &&... systems)
Adds multiple functor systems to the same main sub-app schedule.
ExitCode Run()
Runs the application with the given arguments.
void Write(U &&message) const
Writes a single message to the local queue.
Definition writer.hpp:49
void ForEach(const Action &action) const
Executes an action for each matching entity's components.
Definition query.hpp:1408
@ kSuccess
Successful execution.
constexpr Update kUpdate
Builtin update schedule.
Definition schedules.hpp:98
PmrBasicMessageWriter< T > MessageWriter
Alias for BasicMessageWriter bound to a PMR allocator.
Definition writer.hpp:97
BasicQuery< World, std::pmr::polymorphic_allocator<>, Args... > Query
Alias for BasicQuery bound to World with a PMR allocator.
Definition query.hpp:2264
Message that requests the application to exit.

Lifecycle

Run() → Initialize() → runner_(*this) → CleanUp()
  1. Initialize — builds plugins, waits for readiness, finishes plugins, builds scheduler, runs startup.
  2. Runner — defaults to RunDefault (calls Update() each frame until AppExit).
  3. CleanUp — shutdown schedules, plugin destruction, waits for async work.

ShouldExit() reads AppExit from the main world. Systems write it via MessageWriter<AppExit>.

Frame Lifecycle

Each Update() runs one frame through Scheduler::RunFrame:

  1. Reset extract flags.
  2. Update stage (main) — schedules kFirstkLast, then World::Update() (message lifecycle).
  3. Extract stage — main extract schedules, then sub-app extraction (mode-dependent).
  4. Launch sub-app updates — blocking sub-apps in parallel; overlapping only when fresh extract exists.
  5. WaitForSubApps — joins blocking sub-apps.

Sub-Apps

struct PhysicsLabel {};
app.InsertSubApp(PhysicsLabel{}, helios::app::SubApp{});
app.GetSubApp<PhysicsLabel>().SetExtractFunction(
[](const helios::ecs::World& main, helios::ecs::World& sub) {
// Copy data from main into sub world each frame
});
SubApp & GetSubApp(SubAppTypeIndex index) noexcept
Gets the sub-app of the given type.
auto InsertSubApp(this auto &&self, const T &label, SubApp sub_app) -> decltype(std::forward< decltype(self)>(self))
Inserts a sub-app under the given label, if a sub-app with the same label is not already registered.
A sub-application with its own ECS world and scheduler.
Definition sub_app.hpp:144
The World class manages entities with their components and systems.
Definition world.hpp:39
Mode Extraction Update
Blocking (default) Waits for previous update, then extracts. Launched in parallel with other blocking sub-apps; joined at frame end.
Overlapping Skips extraction while update is in flight (up to kMaxOverlappingUpdates). Fire-and-forget when fresh extract is available.
Async Every frame (allow_while_updating=true); user handles thread safety. Background loop from startup until exit.

Plugins

class GamePlugin final : public helios::app::Plugin {
public:
void Build(helios::app::App& app) override {
app.AddSystems(helios::app::kStartup, SetupWorld{});
}
};
app.AddPlugins(GamePlugin{});
auto AddPlugins(this auto &&self, Plugin &&plugin) -> decltype(std::forward< decltype(self)>(self))
Adds plugin instance, if plugin of the same type is not already registered.
Base class for all plugins.
Definition plugin.hpp:14
virtual void Build(App &app)=0
Builds the plugin.
constexpr Startup kStartup
Builtin startup schedule.
Definition schedules.hpp:66

Dynamic plugins export helios_plugin_create and helios_plugin_type_id (see dynamic_plugin.hpp).

Custom Runner

while (!app.ShouldExit()) {
app.Update();
// custom pacing, rendering, etc.
}
});
auto ShouldExit() const noexcept -> std::optional< ExitCode >
Returns an exit code if an AppExit message was written this frame.
auto SetRunner(this auto &&self, RunnerFn runner) noexcept -> decltype(std::forward< decltype(self)>(self))
Sets runner function for the application.
void Update()
Updates the application and its subsystems.
ExitCode
Application exit codes.

Dependencies

  • async — work-stealing executor
  • ecs — world, schedules, systems
  • log — logging
  • utils — type info, traits