Cpp-Taskflow  2.3.0
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 
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 
259 // Procedure: precede
260 template <typename T>
261 void Task::_precede(T&& other) {
262  _node->_precede(other._node);
263 }
264 
265 // Procedure: _precede
266 template <typename T, typename... Ts>
267 void Task::_precede(T&& task, Ts&&... others) {
268  _precede(std::forward<T>(task));
269  _precede(std::forward<Ts>(others)...);
270 }
271 
272 // Function: succeed
273 template <typename... Ts>
274 Task& Task::succeed(Ts&&... tasks) {
275  //(tasks._node->_precede(_node), ...);
276  _succeed(std::forward<Ts>(tasks)...);
277  return *this;
278 }
279 
280 // Procedure: succeed
281 template <typename T>
282 void Task::_succeed(T&& other) {
283  other._node->_precede(_node);
284 }
285 
286 // Procedure: _succeed
287 template <typename T, typename... Ts>
288 void Task::_succeed(T&& task, Ts&&... others) {
289  _succeed(std::forward<T>(task));
290  _succeed(std::forward<Ts>(others)...);
291 }
292 
293 // Function: composed_of
295  _node->_handle.emplace<Node::ModuleWork>(&tf);
296  return *this;
297 }
298 
299 // Operator =
300 inline Task& Task::operator = (const Task& rhs) {
301  _node = rhs._node;
302  return *this;
303 }
304 
305 // Operator =
307  _node = ptr;
308  return *this;
309 }
310 
311 // Operator ==
312 inline bool Task::operator == (const Task& rhs) const {
313  return _node == rhs._node;
314 }
315 
316 // Operator !=
317 inline bool Task::operator != (const Task& rhs) const {
318  return _node != rhs._node;
319 }
320 
321 // Function: name
322 inline Task& Task::name(const std::string& name) {
323  _node->_name = name;
324  return *this;
325 }
326 
327 // Procedure: reset
328 inline void Task::reset() {
329  _node = nullptr;
330 }
331 
332 // Procedure: reset_work
333 inline void Task::reset_work() {
334  _node->_handle = nstd::monostate{};
335 }
336 
337 // Function: name
338 inline const std::string& Task::name() const {
339  return _node->_name;
340 }
341 
342 // Function: num_dependents
343 inline size_t Task::num_dependents() const {
344  return _node->num_dependents();
345 }
346 
347 // Function: num_strong_dependents
348 inline size_t Task::num_strong_dependents() const {
349  return _node->num_strong_dependents();
350 }
351 
352 // Function: num_weak_dependents
353 inline size_t Task::num_weak_dependents() const {
354  return _node->num_weak_dependents();
355 }
356 
357 // Function: num_successors
358 inline size_t Task::num_successors() const {
359  return _node->num_successors();
360 }
361 
362 // Function: empty
363 inline bool Task::empty() const {
364  return _node == nullptr;
365 }
366 
367 // Function: has_work
368 inline bool Task::has_work() const {
369  return _node ? _node->_handle.index() != 0 : false;
370 }
371 
372 // Function: for_each_successor
373 template <typename V>
374 void Task::for_each_successor(V&& visitor) const {
375  for(size_t i=0; i<_node->_successors.size(); ++i) {
376  visitor(Task(_node->_successors[i]));
377  }
378 }
379 
380 // Function: for_each_dependent
381 template <typename V>
382 void Task::for_each_dependent(V&& visitor) const {
383  for(size_t i=0; i<_node->_dependents.size(); ++i) {
384  visitor(Task(_node->_dependents[i]));
385  }
386 }
387 
388 // ----------------------------------------------------------------------------
389 
396 class TaskView {
397 
398  friend class Executor;
399 
400  public:
401 
405  TaskView() = default;
406 
410  TaskView(const Task& task);
411 
415  TaskView(const TaskView& other);
416 
420  TaskView& operator = (const TaskView& other);
421 
425  TaskView& operator = (const Task& other);
426 
431 
435  bool operator == (const TaskView&) const;
436 
440  bool operator != (const TaskView&) const;
441 
445  const std::string& name() const;
446 
450  size_t num_successors() const;
451 
455  size_t num_dependents() const;
456 
460  size_t num_strong_dependents() const;
461 
465  size_t num_weak_dependents() const;
466 
470  void reset();
471 
475  bool empty() const;
476 
480  template <typename V>
481  void for_each_successor(V&& visitor) const;
482 
486  template <typename V>
487  void for_each_dependent(V&& visitor) const;
488 
489  private:
490 
491  TaskView(Node*);
492 
493  Node* _node {nullptr};
494 };
495 
496 // Constructor
497 inline TaskView::TaskView(Node* node) : _node {node} {
498 }
499 
500 // Constructor
501 inline TaskView::TaskView(const TaskView& rhs) : _node {rhs._node} {
502 }
503 
504 // Constructor
505 inline TaskView::TaskView(const Task& task) : _node {task._node} {
506 }
507 
508 // Operator =
510  _node = rhs._node;
511  return *this;
512 }
513 
514 // Operator =
515 inline TaskView& TaskView::operator = (const Task& rhs) {
516  _node = rhs._node;
517  return *this;
518 }
519 
520 // Operator =
522  _node = ptr;
523  return *this;
524 }
525 
526 // Function: name
527 inline const std::string& TaskView::name() const {
528  return _node->_name;
529 }
530 
531 // Function: num_dependents
532 inline size_t TaskView::num_dependents() const {
533  return _node->num_dependents();
534 }
535 
536 // Function: num_strong_dependents
537 inline size_t TaskView::num_strong_dependents() const {
538  return _node->num_strong_dependents();
539 }
540 
541 // Function: num_weak_dependents
542 inline size_t TaskView::num_weak_dependents() const {
543  return _node->num_weak_dependents();
544 }
545 
546 // Function: num_successors
547 inline size_t TaskView::num_successors() const {
548  return _node->num_successors();
549 }
550 
551 // Function: reset
552 inline void TaskView::reset() {
553  _node = nullptr;
554 }
555 
556 // Function: empty
557 inline bool TaskView::empty() const {
558  return _node == nullptr;
559 }
560 
561 // Operator ==
562 inline bool TaskView::operator == (const TaskView& rhs) const {
563  return _node == rhs._node;
564 }
565 
566 // Operator !=
567 inline bool TaskView::operator != (const TaskView& rhs) const {
568  return _node != rhs._node;
569 }
570 
571 // Function: for_each_successor
572 template <typename V>
573 void TaskView::for_each_successor(V&& visitor) const {
574  for(size_t i=0; i<_node->_successors.size(); ++i) {
575  visitor(TaskView(_node->_successors[i]));
576  }
577 }
578 
579 // Function: for_each_dependent
580 template <typename V>
581 void TaskView::for_each_dependent(V&& visitor) const {
582  for(size_t i=0; i<_node->_dependents.size(); ++i) {
583  visitor(TaskView(_node->_dependents[i]));
584  }
585 }
586 
587 } // end of namespace tf. ---------------------------------------------------
588 
589 
size_t num_dependents() const
queries the number of predecessors of the task
Definition: task.hpp:343
void reset_work()
resets the associated work to a placeholder
Definition: task.hpp:333
void reset()
resets the task handle to null
Definition: task.hpp:328
TaskView()=default
constructs an empty task view
bool operator!=(const TaskView &) const
compares if two taskviews are associated with different tasks
Definition: task.hpp:567
void for_each_dependent(V &&visitor) const
applies an visitor callable to each dependents of the task
Definition: task.hpp:581
size_t num_weak_dependents() const
queries the number of weak dependents of the task
Definition: task.hpp:542
size_t num_successors() const
queries the number of successors of the task
Definition: task.hpp:547
Definition: taskflow.hpp:5
bool operator==(const Task &rhs) const
compares if two tasks are associated with the same graph node
Definition: task.hpp:312
std::enable_if_t< is_static_task_v< C >, Task > & work(C &&callable)
assigns a static task
Definition: flow_builder.hpp:943
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition: task.hpp:274
void for_each_successor(V &&visitor) const
applies an visitor callable to each successor of the task
Definition: task.hpp:573
bool operator!=(const Task &rhs) const
compares if two tasks are not associated with the same graph node
Definition: task.hpp:317
bool empty() const
queries if the task view is empty
Definition: task.hpp:557
size_t num_strong_dependents() const
queries the number of strong dependents of the task
Definition: task.hpp:537
Task & operator=(const Task &)
replaces the contents with a copy of the other task
Definition: task.hpp:300
void for_each_dependent(V &&visitor) const
applies an visitor callable to each dependents of the task
Definition: task.hpp:382
the class to create a task dependency graph
Definition: core/taskflow.hpp:18
const std::string & name() const
queries the name of the task
Definition: task.hpp:338
an immutable accessor class to a task node, mainly used in the tf::ExecutorObserver interface...
Definition: task.hpp:396
bool empty() const
queries if the task handle points to a task node
Definition: task.hpp:363
void reset()
resets to an empty view
Definition: task.hpp:552
size_t num_strong_dependents() const
queries the number of strong dependents of the task
Definition: task.hpp:348
Building blocks 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:358
size_t num_weak_dependents() const
queries the number of weak dependents of the task
Definition: task.hpp:353
task 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:374
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:509
bool operator==(const TaskView &) const
compares if two taskviews are associated with the same task
Definition: task.hpp:562
size_t num_dependents() const
queries the number of predecessors of the task
Definition: task.hpp:532
bool has_work() const
queries if the task has a work assigned
Definition: task.hpp:368
const std::string & name() const
queries the name of the task
Definition: task.hpp:527
Task & composed_of(Taskflow &)
creates a module task from a taskflow
Definition: task.hpp:294