-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimple_dag_executor.cpp
More file actions
108 lines (91 loc) · 3.2 KB
/
simple_dag_executor.cpp
File metadata and controls
108 lines (91 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
一个轻量级、线程安全(单线程执行)、基于拓扑排序的有向无环图
g++ simple_dag_executor.cpp -o simple_dag_executor
*/
#include <iostream>
#include <unordered_map>
#include <vector>
#include <functional>
#include <queue>
#include <stdexcept>
#include <set>
class DAGExecutor{
public:
using Task = std::function<void()>;
using NodeId = std::string;
// 添加一个任务节点
void addNode(NodeId id, Task task) {
nodes_[id] = std::move(task);
inDegree_[id];//初始化入度为0
}
// 添加依赖
void addDependency(const NodeId& from, const NodeId& to){
/// 查询节点表中有无节点
if(nodes_.find(from) == nodes_.end() || nodes_.find(to) == nodes_.end()){
throw std::invalid_argument("Node not found in DAG");
}
// from->to 表示to依赖于from, from先于to执行
adjList_[from].push_back(to);
// to节点入度+1
inDegree_[to]++;
}
// 执行所有任务(按拓扑排序)
void execute(){
std::queue<NodeId> q; // 执行队列
std::unordered_map<NodeId, int> inDeg = inDegree_;// 复制入度表,避免修改原数据
// 将所有入度为0的节点入队
for(const auto& node:nodes_){
if(inDeg[node.first] == 0){
q.push(node.first);
}
}
std::vector<NodeId> topoOrder;
// kahn算法遍历图
while(!q.empty()){
NodeId u = q.front();
q.pop();
topoOrder.push_back(u);
// 遍历所有邻居
for(const NodeId& v:adjList_[u]){
inDeg[v]--;// 邻居入度减一
if(inDeg[v] == 0){// 如果后继节点,入度变成了0,表示前置依赖都就绪了
q.push(v);
}
}
}
// 检测环: 如果拓扑序列的长度 ≠ 节点总数,则存在环
if(topoOrder.size() != nodes_.size()){
throw std::runtime_error("Cycle detected in Dag");
}
// 按拓扑序执行任务
for(const auto& id :topoOrder){
std::cout << "Executing:" << id << std::endl;
nodes_[id]();// 执行任务
}
}
private:
std::unordered_map<NodeId, Task> nodes_; // 节点ID->任务
std::unordered_map<NodeId, std::vector<NodeId>> adjList_; // 邻接矩阵
std::unordered_map<NodeId, int> inDegree_; // 入度表
};
// ================== 示例用法 ==================
int main() {
DAGExecutor dag;
// 添加任务
dag.addNode("A", []() { std::cout << "Task A done\n"; });
dag.addNode("B", []() { std::cout << "Task B done\n"; });
dag.addNode("C", []() { std::cout << "Task C done\n"; });
dag.addNode("D", []() { std::cout << "Task D done\n"; });
// 添加依赖: A → B, A → C, B → D, C → D
dag.addDependency("A", "B");
dag.addDependency("A", "C");
dag.addDependency("B", "D");
dag.addDependency("C", "D");
try {
dag.execute();
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}