Cpp-Taskflow  2.3.1
task.hpp
1 #pragma once
2 
3 #include "graph.hpp"
4 
5 namespace tf {
6 
7 // ----------------------------------------------------------------------------
8 // Task Traits
9 // ----------------------------------------------------------------------------
10 
16 template <typename C>
17 constexpr bool is_static_task_v = is_invocable_r_v<void, C> &&
18  !is_invocable_r_v<int, C>;
19 
25 template <typename C>
26 constexpr bool is_dynamic_task_v = is_invocable_r_v<void, C, Subflow&>;
27 
33 template <typename C>
34 constexpr bool is_condition_task_v = is_invocable_r_v<int, C>;
35 
36 // ----------------------------------------------------------------------------
37 // Task
38 // ----------------------------------------------------------------------------
39 
51 class Task {
52 
53  friend class FlowBuilder;
54  friend class Taskflow;
55  friend class TaskView;
56 
57  public:
58 
62  Task() = default;
63 
67  Task(const Task& other);
68 
72  Task& operator = (const Task&);
73 
78 
82  bool operator == (const Task& rhs) const;
83 
87  bool operator != (const Task& rhs) const;
88 
92  const std::string& name() const;
93 
97  size_t num_successors() const;
98 
102  size_t num_dependents() const;
103 
107  size_t num_strong_dependents() const;
108 
112  size_t num_weak_dependents() const;
113 
121  Task& name(const std::string& name);
122 
132  template <typename C>
133  std::enable_if_t<is_static_task_v<C>, Task>& work(C&& callable);
134 
144  template <typename C>
145  std::enable_if_t<is_dynamic_task_v<C>, Task>& work(C&& callable);
146 
156  template <typename C>
157  std::enable_if_t<is_condition_task_v<C>, Task>& work(C&& callable);
158 
166  Task& composed_of(Taskflow& taskflow);
167 
177  template <typename... Ts>
178  Task& precede(Ts&&... tasks);
179 
189  template <typename... Ts>
190  Task& succeed(Ts&&... tasks);
191 
195  void reset();
196 
200  void reset_work();
201 
205  bool empty() const;
206 
210  bool has_work() const;
211 
215  template <typename V>
216  void for_each_successor(V&& visitor) const;
217 
221  template <typename V>
222  void for_each_dependent(V&& visitor) const;
223 
224  private:
225 
226  Task(Node*);
227 
228  Node* _node {nullptr};
229 
230  template <typename T>
231  void _precede(T&&);
232 
233  template <typename T, typename... Rest>
234  void _precede(T&&, Rest&&...);
235 
236  template <typename T>
237  void _succeed(T&&);
238 
239  template <typename T, typename... Rest>
240  void _succeed(T&&, Rest&&...);
241 };
242 
243 // Constructor
244 inline Task::Task(Node* node) : _node {node} {
245 }
246 
247 // Constructor
248 inline Task::Task(const Task& rhs) : _node {rhs._node} {
249 }
250 
251 // Function: precede
252 template <typename... Ts>
253 Task& Task::precede(Ts&&... tasks) {
254  //(_node->_precede(tgts._node), ...);
255  _precede(std::forward<Ts>(tasks)...);
256  return *this;
257 }
258 
260 // Procedure: _precede
261 template <typename T>
262 void Task::_precede(T&& other) {
263  _node->_precede(other._node);
264 }
265 
267 // Procedure: _precede
268 template <typename T, typename... Ts>
269 void Task::_precede(T&& task, Ts&&... others) {
270  _precede(std::forward<T>(task));
271  _precede(std::forward<Ts>(others)...);
272 }
273 
274 // Function: succeed
275 template <typename... Ts>
276 Task& Task::succeed(Ts&&... tasks) {
277  //(tasks._node->_precede(_node), ...);
278  _succeed(std::forward<Ts>(tasks)...);
279  return *this;
280 }
281 
283 // Procedure: succeed
284 template <typename T>
285 void Task::_succeed(T&& other) {
286  other._node->_precede(_node);
287 }
288 
290 // Procedure: _succeed
291 template <typename T, typename... Ts>
292 void Task::_succeed(T&& task, Ts&&... others) {
293  _succeed(std::forward<T>(task));
294  _succeed(std::forward<Ts>(others)...);
295 }
296 
297 // Function: composed_of
299  _node->_handle.emplace<Node::ModuleWork>(&tf);
300  return *this;
301 }
302 
303 // Operator =
304 inline Task& Task::operator = (const Task& rhs) {
305  _node = rhs._node;
306  return *this;
307 }
308 
309 // Operator =
311  _node = ptr;
312  return *this;
313 }
314 
315 // Operator ==
316 inline bool Task::operator == (const Task& rhs) const {
317  return _node == rhs._node;
318 }
319 
320 // Operator !=
321 inline bool Task::operator != (const Task& rhs) const {
322  return _node != rhs._node;
323 }
324 
325 // Function: name
326 inline Task& Task::name(const std::string& name) {
327  _node->_name = name;
328  return *this;
329 }
330 
331 // Procedure: reset
332 inline void Task::reset() {
333  _node = nullptr;
334 }
335 
336 // Procedure: reset_work
337 inline void Task::reset_work() {
338  _node->_handle = nstd::monostate{};
339 }
340 
341 // Function: name
342 inline const std::string& Task::name() const {
343  return _node->_name;
344 }
345 
346 // Function: num_dependents
347 inline size_t Task::num_dependents() const {
348  return _node->num_dependents();
349 }
350 
351 // Function: num_strong_dependents
352 inline size_t Task::num_strong_dependents() const {
353  return _node->num_strong_dependents();
354 }
355 
356 // Function: num_weak_dependents
357 inline size_t Task::num_weak_dependents() const {
358  return _node->num_weak_dependents();
359 }
360 
361 // Function: num_successors
362 inline size_t Task::num_successors() const {
363  return _node->num_successors();
364 }
365 
366 // Function: empty
367 inline bool Task::empty() const {
368  return _node == nullptr;
369 }
370 
371 // Function: has_work
372 inline bool Task::has_work() const {
373  return _node ? _node->_handle.index() != 0 : false;
374 }
375 
376 // Function: for_each_successor
377 template <typename V>
378 void Task::for_each_successor(V&& visitor) const {
379  for(size_t i=0; i<_node->_successors.size(); ++i) {
380  visitor(Task(_node->_successors[i]));
381  }
382 }
383 
384 // Function: for_each_dependent
385 template <typename V>
386 void Task::for_each_dependent(V&& visitor) const {
387  for(size_t i=0; i<_node->_dependents.size(); ++i) {
388  visitor(Task(_node->_dependents[i]));
389  }
390 }
391 
392 // ----------------------------------------------------------------------------
393 
400 class TaskView {
401 
402  friend class Executor;
403 
404  public:
405 
409  TaskView() = default;
410 
414  TaskView(const Task& task);
415 
419  TaskView(const TaskView& other);
420 
424  TaskView& operator = (const TaskView& other);
425 
429  TaskView& operator = (const Task& other);
430 
435 
439  bool operator == (const TaskView&) const;
440 
444  bool operator != (const TaskView&) const;
445 
449  const std::string& name() const;
450 
454  size_t num_successors() const;
455 
459  size_t num_dependents() const;
460 
464  size_t num_strong_dependents() const;
465 
469  size_t num_weak_dependents() const;
470 
474  void reset();
475 
479  bool empty() const;
480 
484  template <typename V>
485  void for_each_successor(V&& visitor) const;
486 
490  template <typename V>
491  void for_each_dependent(V&& visitor) const;
492 
493  private:
494 
495  TaskView(Node*);
496 
497  Node* _node {nullptr};
498 };
499 
500 // Constructor
501 inline TaskView::TaskView(Node* node) : _node {node} {
502 }
503 
504 // Constructor
505 inline TaskView::TaskView(const TaskView& rhs) : _node {rhs._node} {
506 }
507 
508 // Constructor
509 inline TaskView::TaskView(const Task& task) : _node {task._node} {
510 }
511 
512 // Operator =
514  _node = rhs._node;
515  return *this;
516 }
517 
518 // Operator =
519 inline TaskView& TaskView::operator = (const Task& rhs) {
520  _node = rhs._node;
521  return *this;
522 }
523 
524 // Operator =
526  _node = ptr;
527  return *this;
528 }
529 
530 // Function: name
531 inline const std::string& TaskView::name() const {
532  return _node->_name;
533 }
534 
535 // Function: num_dependents
536 inline size_t TaskView::num_dependents() const {
537  return _node->num_dependents();
538 }
539 
540 // Function: num_strong_dependents
541 inline size_t TaskView::num_strong_dependents() const {
542  return _node->num_strong_dependents();
543 }
544 
545 // Function: num_weak_dependents
546 inline size_t TaskView::num_weak_dependents() const {
547  return _node->num_weak_dependents();
548 }
549 
550 // Function: num_successors
551 inline size_t TaskView::num_successors() const {
552  return _node->num_successors();
553 }
554 
555 // Function: reset
556 inline void TaskView::reset() {
557  _node = nullptr;
558 }
559 
560 // Function: empty
561 inline bool TaskView::empty() const {
562  return _node == nullptr;
563 }
564 
565 // Operator ==
566 inline bool TaskView::operator == (const TaskView& rhs) const {
567  return _node == rhs._node;
568 }
569 
570 // Operator !=
571 inline bool TaskView::operator != (const TaskView& rhs) const {
572  return _node != rhs._node;
573 }
574 
575 // Function: for_each_successor
576 template <typename V>
577 void TaskView::for_each_successor(V&& visitor) const {
578  for(size_t i=0; i<_node->_successors.size(); ++i) {
579  visitor(TaskView(_node->_successors[i]));
580  }
581 }
582 
583 // Function: for_each_dependent
584 template <typename V>
585 void TaskView::for_each_dependent(V&& visitor) const {
586  for(size_t i=0; i<_node->_dependents.size(); ++i) {
587  visitor(TaskView(_node->_dependents[i]));
588  }
589 }
590 
591 } // end of namespace tf. ---------------------------------------------------
592 
593 
size_t num_dependents() const
queries the number of predecessors of the task
Definition: task.hpp:347
void reset_work()
resets the associated work to a placeholder
Definition: task.hpp:337
void reset()
resets the task handle to null
Definition: task.hpp:332
TaskView()=default
constructs an empty task view
bool operator!=(const TaskView &) const
compares if two taskviews are associated with different tasks
Definition: task.hpp:571
void for_each_dependent(V &&visitor) const
applies an visitor callable to each dependents of the task
Definition: task.hpp:585
size_t num_weak_dependents() const
queries the number of weak dependents of the task
Definition: task.hpp:546
Task & composed_of(Taskflow &taskflow)
creates a module task from a taskflow
Definition: task.hpp:298
size_t num_successors() const
queries the number of successors of the task
Definition: task.hpp:551
Definition: error.hpp:9
bool operator==(const Task &rhs) const
compares if two tasks are associated with the same graph node
Definition: task.hpp:316
std::enable_if_t< is_static_task_v< C >, Task > & work(C &&callable)
assigns a static task
Definition: flow_builder.hpp:969
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition: task.hpp:276
void for_each_successor(V &&visitor) const
applies an visitor callable to each successor of the task
Definition: task.hpp:577
bool operator!=(const Task &rhs) const
compares if two tasks are not associated with the same graph node
Definition: task.hpp:321
bool empty() const
queries if the task view is empty
Definition: task.hpp:561
size_t num_strong_dependents() const
queries the number of strong dependents of the task
Definition: task.hpp:541
Task & operator=(const Task &)
replaces the contents with a copy of the other task
Definition: task.hpp:304
void for_each_dependent(V &&visitor) const
applies an visitor callable to each dependents of the task
Definition: task.hpp:386
the class to create a task dependency graph
Definition: taskflow.hpp:18
const std::string & name() const
queries the name of the task
Definition: task.hpp:342
an immutable accessor class to a task node, mainly used in the tf::ExecutorObserver interface...
Definition: task.hpp:400
bool empty() const
queries if the task handle points to a task node
Definition: task.hpp:367
void reset()
resets to an empty view
Definition: task.hpp:556
size_t num_strong_dependents() const
queries the number of strong dependents of the task
Definition: task.hpp:352
Building methods of a task dependency graph.
Definition: flow_builder.hpp:13
size_t num_successors() const
queries the number of successors of the task
Definition: task.hpp:362
size_t num_weak_dependents() const
queries the number of weak dependents of the task
Definition: task.hpp:357
handle to a node in a task dependency graph
Definition: task.hpp:51
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition: task.hpp:253
void for_each_successor(V &&visitor) const
applies an visitor callable to each successor of the task
Definition: task.hpp:378
Task()=default
constructs an empty task
The executor class to run a taskflow graph.
Definition: executor.hpp:33
TaskView & operator=(const TaskView &other)
replaces the contents with a copy of the other task
Definition: task.hpp:513
bool operator==(const TaskView &) const
compares if two taskviews are associated with the same task
Definition: task.hpp:566
size_t num_dependents() const
queries the number of predecessors of the task
Definition: task.hpp:536
bool has_work() const
queries if the task has a work assigned
Definition: task.hpp:372
const std::string & name() const
queries the name of the task
Definition: task.hpp:531