Class ModuleStack¶
Defined in File module_stack.h
Class Documentation¶
-
class ModuleStack¶
Dependency injection container managing module lifetime and execution.
ModuleStack is the central registry for all modules in a Portal application. It handles module registration, dependency resolution through topological sorting, and provides lifecycle facade methods that execute modules in dependency order.
After modules are registered with add_module(), call build_dependency_graph() to perform topological sorting. This organizes modules by dependency level and creates pre-sorted vectors for each tag type.
The lifecycle facade methods (begin_frame, update, etc.) iterate the appropriate tag-specific vectors, ensuring modules execute in dependency order with zero runtime overhead for resolution.
Example usage:
ModuleStack modules; modules.add_module<Renderer>(STRING_ID("Renderer")); modules.add_module<ResourceRegistry>(STRING_ID("Resources")); modules.add_module<GameLogic>(STRING_ID("Game")); modules.build_dependency_graph(); // Must call after registration // In game loop: // Calls update() on modules in dependency order modules.update(frame_context);
Public Functions
-
~ModuleStack()¶
-
void clean()¶
Clean up all modules in reverse dependency order. Called by destructor, but can be called manually for explicit cleanup.
-
template<typename T, typename ...Args>
inline T &add_module(Args&&... args)¶ Register a new module and construct it in-place.
The module receives a reference to this ModuleStack as its first constructor argument, followed by any additional arguments. During construction, the module’s dependencies are resolved using ModuleLookup.
Marks the dependency graph as dirty, requiring rebuild before execution.
- Template Parameters:
T – The module type, must inherit from BaseModule
Args – Additional constructor argument types
- Parameters:
args – Arguments forwarded to the module’s constructor (after ModuleStack&)
- Throws:
std::runtime_error – if module dependencies cannot be resolved
- Returns:
Reference to the newly constructed module
-
inline std::span<std::unique_ptr<BaseModule>> list_modules()¶
Get a span of all registered modules for introspection.
- Returns:
Span of unique pointers to all registered modules
-
void build_dependency_graph()¶
Perform topological sort of modules based on dependencies.
This method organizes modules into dependency levels using a depth-first search algorithm. Modules with no dependencies are level 0, and each module’s level is one plus the maximum level of its dependencies.
The sorted modules are organized into:
dependency_graph: vector-of-vectors where each inner vector is a dependency level
Tag-specific vectors (update_modules, etc.): pre-sorted for efficient iteration
Must be called after module registration and before execution.
- Throws:
std::runtime_error – if circular dependencies are detected
-
void begin_frame(FrameContext &frame) const¶
Call begin_frame() on all FrameLifecycle modules in dependency order.
- Parameters:
frame – Per-frame context data
-
void end_frame(FrameContext &frame) const¶
Call end_frame() on all FrameLifecycle modules in reverse dependency order.
- Parameters:
frame – Per-frame context data
-
void update(FrameContext &frame) const¶
Call update() on all Update-tagged modules in dependency order.
- Parameters:
frame – Per-frame context data
-
void post_update(FrameContext &frame) const¶
Call post_update() on all PostUpdate-tagged modules in dependency order.
- Parameters:
frame – Per-frame context data
-
void gui_update(FrameContext &frame) const¶
Call gui_update() on all GuiUpdate-tagged modules in dependency order.
- Parameters:
frame – Per-frame context data
-
void on_event(Event &event) const¶
Call on_event() on all Event-tagged modules.
- Parameters:
event – The event to dispatch
-
inline const std::vector<std::vector<BaseModule*>> &get_dependency_graph() const¶
Get the computed dependency graph for introspection.
- Returns:
Vector of dependency levels, where each level is a vector of modules
-
~ModuleStack()¶