Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
dag.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <cstddef>
6#include <cstdint>
7#include <expected>
8#include <span>
9#include <string>
10#include <unordered_map>
11#include <vector>
12
13namespace helios::ecs {
14
15enum class DagErrorKind : uint8_t {
18};
19
20struct DagError {
22 std::string message;
23 std::vector<SystemId> involved_nodes;
24};
25
26template <typename T>
27using DagResult = std::expected<T, DagError>;
28
29/**
30 * @brief Directed acyclic graph used to compute the topological execution order
31 * of systems within a schedule.
32 */
33class Dag {
34public:
35 Dag() = default;
36 Dag(const Dag&) = delete;
37 Dag(Dag&&) noexcept = default;
38 ~Dag() = default;
39
40 Dag& operator=(const Dag&) = delete;
41 Dag& operator=(Dag&&) noexcept = default;
42
43 /**
44 * @brief Adds a node for `id`.
45 * @return Internal index of the added node
46 */
47 size_t AddNode(SystemId id);
48
49 /**
50 * @brief Adds a directed edge from `from` to `to` (from must run before to).
51 * @details Does **not** perform per-insertion cycle detection - O(1).
52 * Call `Sort()` after all edges have been added; it detects cycles
53 * as a side effect of Kahn's topological sort at O(V+E) total cost.
54 * @return Result of the operation
55 */
56 [[nodiscard]] auto AddEdge(SystemId from, SystemId to) -> DagResult<void>;
57
58 /**
59 * @brief Performs a topological sort and returns system ids in execution
60 * order.
61 * @return Sorted ids on success, `DagError` on failure
62 */
63 [[nodiscard]] auto Sort() const -> DagResult<std::vector<SystemId>>;
64
65 /**
66 * @brief Gets the internal index of `id`.
67 * @return Internal index on success, `DagError` on failure
68 */
69 [[nodiscard]] auto IndexOf(SystemId id) const -> DagResult<size_t>;
70
71 /**
72 * @brief Checks if this DAG has a cycle.
73 * @return `true` if a cycle is detected, `false` otherwise
74 */
75 [[nodiscard]] bool HasCycle() const;
76
77 /**
78 * @brief Checks whether `to` is reachable from `from` along directed edges.
79 * @param from Source system id
80 * @param to Target system id
81 * @return True if a directed path exists from `from` to `to`
82 */
83 [[nodiscard]] bool Reachable(SystemId from, SystemId to) const;
84
85 /**
86 * @brief Gets a read-only view of all nodes (in insertion order).
87 * @return Read-only span of system ids in insertion order
88 */
89 [[nodiscard]] auto Nodes() const noexcept -> std::span<const SystemId> {
90 return node_ids_;
91 }
92
93private:
94 enum class NodeKind : uint8_t {
95 kSystem,
96 kSyncPoint,
97 };
98
99 struct Node {
100 SystemId id;
101 NodeKind kind = NodeKind::kSystem;
102 size_t insertion_index = 0;
103 };
104
105 [[nodiscard]] auto ExtractCyclePath() const -> std::vector<size_t>;
106
107 std::vector<Node> nodes_;
108 std::vector<SystemId> node_ids_;
109 std::vector<std::vector<size_t>> adjacency_;
110 std::unordered_map<size_t, size_t> id_to_index_;
111};
112
113} // namespace helios::ecs
Dag(const Dag &)=delete
Dag(Dag &&) noexcept=default
auto Nodes() const noexcept -> std::span< const SystemId >
Gets a read-only view of all nodes (in insertion order).
Definition dag.hpp:89
size_t AddNode(SystemId id)
Adds a node for id.
Definition dag.cpp:16
auto Sort() const -> DagResult< std::vector< SystemId > >
Performs a topological sort and returns system ids in execution order.
Definition dag.cpp:65
auto AddEdge(SystemId from, SystemId to) -> DagResult< void >
Adds a directed edge from from to to (from must run before to).
Definition dag.cpp:40
bool HasCycle() const
Checks if this DAG has a cycle.
Definition dag.cpp:194
bool Reachable(SystemId from, SystemId to) const
Checks whether to is reachable from from along directed edges.
Definition dag.cpp:230
auto IndexOf(SystemId id) const -> DagResult< size_t >
Gets the internal index of id.
Definition dag.cpp:26
std::expected< T, DagError > DagResult
Definition dag.hpp:27
STL namespace.
DagErrorKind kind
Definition dag.hpp:21
std::vector< SystemId > involved_nodes
Definition dag.hpp:23
std::string message
Definition dag.hpp:22
Id for systems.
Definition system.hpp:146