Cpp-Taskflow  2.3.0
core/taskflow.hpp
1 #pragma once
2 
3 #include <stack>
4 
5 #include "flow_builder.hpp"
6 #include "topology.hpp"
7 
8 namespace tf {
9 
10 // ----------------------------------------------------------------------------
11 
18 class Taskflow : public FlowBuilder {
19 
20  friend class Topology;
21  friend class Executor;
22  friend class FlowBuilder;
23 
24  public:
25 
29  Taskflow(const std::string& name);
30 
34  Taskflow();
35 
39  virtual ~Taskflow();
40 
46  void dump(std::ostream& ostream) const;
47 
51  std::string dump() const;
52 
56  size_t num_tasks() const;
57 
61  bool empty() const;
62 
68  tf::Taskflow& name(const std::string&);
69 
73  const std::string& name() const ;
74 
78  void clear();
79 
83  template <typename V>
84  void for_each_task(V&& visitor) const;
85 
86  private:
87 
88  std::string _name;
89 
90  Graph _graph;
91 
92  std::mutex _mtx;
93 
94  std::list<Topology> _topologies;
95 
96  void _dump(std::ostream&, const Taskflow*) const;
97 
98  void _dump(
99  std::ostream&,
100  const Node*,
103  ) const;
104 
105  void _dump(
106  std::ostream&,
107  const Graph&,
110  ) const;
111 };
112 
113 // Constructor
115  FlowBuilder {_graph},
116  _name {name} {
117 }
118 
119 // Constructor
120 inline Taskflow::Taskflow() : FlowBuilder{_graph} {
121 }
122 
123 // Destructor
125  assert(_topologies.empty());
126 }
127 
128 // Procedure:
129 inline void Taskflow::clear() {
130  _graph.clear();
131 }
132 
133 // Function: num_noces
134 inline size_t Taskflow::num_tasks() const {
135  return _graph.size();
136 }
137 
138 // Function: empty
139 inline bool Taskflow::empty() const {
140  return _graph.empty();
141 }
142 
143 // Function: name
145  _name = name;
146  return *this;
147 }
148 
149 // Function: name
150 inline const std::string& Taskflow::name() const {
151  return _name;
152 }
153 
154 // Function: for_each_task
155 template <typename V>
156 void Taskflow::for_each_task(V&& visitor) const {
157  for(size_t i=0; i<_graph._nodes.size(); ++i) {
158  visitor(Task(_graph._nodes[i]));
159  }
160 }
161 
162 // Procedure: dump
163 inline std::string Taskflow::dump() const {
164  std::ostringstream oss;
165  dump(oss);
166  return oss.str();
167 }
168 
169 // Function: dump
170 inline void Taskflow::dump(std::ostream& os) const {
171  os << "digraph Taskflow {\n";
172  _dump(os, this);
173  os << "}\n";
174 }
175 
176 // Procedure: _dump
177 inline void Taskflow::_dump(std::ostream& os, const Taskflow* top) const {
178 
181 
182  stack.push(top);
183  visited.insert(top);
184 
185  while(!stack.empty()) {
186 
187  auto f = stack.top();
188  stack.pop();
189 
190  os << "subgraph cluster_p" << f << " {\nlabel=\"Taskflow: ";
191  if(f->_name.empty()) os << 'p' << f;
192  else os << f->_name;
193  os << "\";\n";
194  _dump(os, f->_graph, stack, visited);
195  os << "}\n";
196  }
197 }
198 
199 // Procedure: _dump
200 inline void Taskflow::_dump(
201  std::ostream& os,
202  const Node* node,
205 ) const {
206 
207  os << 'p' << node << "[label=\"";
208  if(node->_name.empty()) os << 'p' << node;
209  else os << node->_name;
210  os << "\" ";
211 
212  // condition node is colored green
213  if(node->_work.index() == Node::CONDITION_WORK) {
214  os << " shape=diamond color=black fillcolor=aquamarine style=filled";
215  }
216 
217  os << "];\n";
218 
219  for(size_t s=0; s<node->_successors.size(); ++s) {
220  if(node->_work.index() == Node::CONDITION_WORK) {
221  // case edge is dashed
222  os << 'p' << node << " -> p" << node->_successors[s]
223  << " [style=dashed label=\"" << s << "\"];\n";
224  }
225  else {
226  os << 'p' << node << " -> p" << node->_successors[s] << ";\n";
227  }
228  }
229 
230  // subflow join node
231  if(node->_parent && node->_successors.size() == 0) {
232  os << 'p' << node << " -> p" << node->_parent << ";\n";
233  }
234 
235  if(node->_subgraph && !node->_subgraph->empty()) {
236 
237  os << "subgraph cluster_p" << node << " {\nlabel=\"Subflow: ";
238  if(node->_name.empty()) os << 'p' << node;
239  else os << node->_name;
240 
241  os << "\";\n" << "color=blue\n";
242  _dump(os, *(node->_subgraph), stack, visited);
243  os << "}\n";
244  }
245 }
246 
247 // Procedure: _dump
248 inline void Taskflow::_dump(
249  std::ostream& os,
250  const Graph& graph,
253 ) const {
254 
255  for(const auto& n : graph._nodes) {
256  // regular task
257  if(auto module = n->_module; !module) {
258  _dump(os, n, stack, visited);
259  }
260  // module task
261  else {
262  os << 'p' << n << "[shape=box, color=blue, label=\"";
263  if(n->_name.empty()) os << n;
264  else os << n->_name;
265  os << " [Taskflow: ";
266  if(module->_name.empty()) os << 'p' << module;
267  else os << module->_name;
268  os << "]\"];\n";
269 
270  if(visited.find(module) == visited.end()) {
271  visited.insert(module);
272  stack.push(module);
273  }
274 
275  for(const auto s : n->_successors) {
276  os << 'p' << n << "->" << 'p' << s << ";\n";
277  }
278  }
279  }
280 }
281 
282 // ----------------------------------------------------------------------------
283 // Backward compatibility
284 // ----------------------------------------------------------------------------
285 
286 using Framework = Taskflow;
287 
288 } // end of namespace tf. ---------------------------------------------------
289 
Taskflow()
constructs a taskflow
Definition: core/taskflow.hpp:120
Definition: taskflow.hpp:5
void for_each_task(V &&visitor) const
applies an visitor callable to each task in the taskflow
Definition: core/taskflow.hpp:156
const std::string & name() const
queries the name of the taskflow
Definition: core/taskflow.hpp:150
void clear()
clears the associated task dependency graph
Definition: core/taskflow.hpp:129
the class to create a task dependency graph
Definition: core/taskflow.hpp:18
bool empty() const
queries the emptiness of the taskflow
Definition: core/taskflow.hpp:139
std::string dump() const
dumps the taskflow in DOT format to a std::string
Definition: core/taskflow.hpp:163
Building blocks of a task dependency graph.
Definition: flow_builder.hpp:13
task handle to a node in a task dependency graph
Definition: task.hpp:22
The executor class to run a taskflow graph.
Definition: executor.hpp:33
size_t num_tasks() const
queries the number of tasks in the taskflow
Definition: core/taskflow.hpp:134
virtual ~Taskflow()
destroy the taskflow (virtual call)
Definition: core/taskflow.hpp:124