Taskflow  2.7.0
flow_builder.hpp
1 #pragma once
2 
3 #include "task.hpp"
4 
5 namespace tf {
6 
13 class FlowBuilder {
14 
15  friend class Executor;
16 
17  public:
18 
28  template <typename C>
29  std::enable_if_t<is_static_task_v<C>, Task> emplace(C&& callable);
30 
40  template <typename C>
41  std::enable_if_t<is_dynamic_task_v<C>, Task> emplace(C&& callable);
42 
52  template <typename C>
53  std::enable_if_t<is_condition_task_v<C>, Task> emplace(C&& callable);
54 
55 #ifdef TF_ENABLE_CUDA
56 
65  template <typename C>
66  std::enable_if_t<is_cudaflow_task_v<C>, Task> emplace(C&& callable);
67 #endif
68 
78  template <typename... C, std::enable_if_t<(sizeof...(C)>1), void>* = nullptr>
79  auto emplace(C&&... callables);
80 
87  Task composed_of(Taskflow& taskflow);
88 
94  Task placeholder();
95 
101  void linearize(std::vector<Task>& tasks);
102 
109 
110  // ------------------------------------------------------------------------
111  // parallel iterations
112  // ------------------------------------------------------------------------
113 
141  template <typename B, typename E, typename C>
142  Task for_each(B&& first, E&& last, C&& callable);
143 
165  template <typename B, typename E, typename C, typename H = size_t>
166  Task for_each_guided(B&& beg, E&& end, C&& callable, H&& chunk_size = 1);
167 
189  template <typename B, typename E, typename C, typename H = size_t>
190  Task for_each_dynamic(B&& beg, E&& end, C&& callable, H&& chunk_size = 1);
191 
213  template <typename B, typename E, typename C, typename H = size_t>
215  B&& beg, E&& end, C&& callable, H&& chunk_size = 0
216  );
217 
254  template <typename B, typename E, typename S, typename C>
255  Task for_each_index(B&& first, E&& last, S&& step, C&& callable);
256 
280  template <typename B, typename E, typename S, typename C, typename H = size_t>
282  B&& beg, E&& end, S&& step, C&& callable, H&& chunk_size = 1
283  );
284 
308  template <typename B, typename E, typename S, typename C, typename H = size_t>
310  B&& beg, E&& end, S&& step, C&& callable, H&& chunk_size = 1
311  );
312 
336  template <typename B, typename E, typename S, typename C, typename H = size_t>
338  B&& beg, E&& end, S&& step, C&& callable, H&& chunk_size = 0
339  );
340 
341  // ------------------------------------------------------------------------
342  // reduction
343  // ------------------------------------------------------------------------
344 
372  template <typename B, typename E, typename T, typename O>
373  Task reduce(B&& first, E&& last, T& init, O&& bop);
374 
396  template <typename B, typename E, typename T, typename O, typename H = size_t>
398  B&& first, E&& last, T& init, O&& bop, H&& chunk_size = 1
399  );
400 
422  template <typename B, typename E, typename T, typename O, typename H = size_t>
424  B&& first, E&& last, T& init, O&& bop, H&& chunk_size = 1
425  );
426 
448  template <typename B, typename E, typename T, typename O, typename H = size_t>
450  B&& first, E&& last, T& init, O&& bop, H&& chunk_size = 0
451  );
452 
453  // ------------------------------------------------------------------------
454  // transfrom and reduction
455  // ------------------------------------------------------------------------
456 
486  template <typename B, typename E, typename T, typename BOP, typename UOP>
487  Task transform_reduce(B&& first, E&& last, T& init, BOP&& bop, UOP&& uop);
488 
512  template <typename B, typename E, typename T, typename BOP, typename UOP, typename H = size_t>
514  B&& first, E&& last, T& init, BOP&& bop, UOP&& uop, H&& chunk_size = 1
515  );
516 
540  template <typename B, typename E, typename T, typename BOP, typename UOP, typename H = size_t>
542  B&& first, E&& last, T& init, BOP&& bop, UOP&& uop, H&& chunk_size = 0
543  );
544 
568  template <typename B, typename E, typename T, typename BOP, typename UOP, typename H = size_t>
570  B&& first, E&& last, T& init, BOP&& bop, UOP&& uop, H&& chunk_size = 1
571  );
572 
573 
574  protected:
575 
579  FlowBuilder(Graph& graph);
580 
584  Graph& _graph;
585 
586  private:
587 
588  template <typename L>
589  void _linearize(L&);
590 };
591 
592 // Constructor
593 inline FlowBuilder::FlowBuilder(Graph& graph) :
594  _graph {graph} {
595 }
596 
597 // Function: emplace
598 template <typename... C, std::enable_if_t<(sizeof...(C)>1), void>*>
599 auto FlowBuilder::emplace(C&&... cs) {
600  return std::make_tuple(emplace(std::forward<C>(cs))...);
601 }
602 
603 // Function: emplace
604 // emplaces a static task
605 template <typename C>
606 std::enable_if_t<is_static_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
607  auto n = _graph.emplace_back(
608  nstd::in_place_type_t<Node::StaticWork>{}, std::forward<C>(c)
609  );
610  return Task(n);
611 }
612 
613 // Function: emplace
614 // emplaces a dynamic task
615 template <typename C>
616 std::enable_if_t<is_dynamic_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
617  auto n = _graph.emplace_back(
618  nstd::in_place_type_t<Node::DynamicWork>{}, std::forward<C>(c)
619  );
620  return Task(n);
621 }
622 
623 // Function: emplace
624 // emplaces a condition task
625 template <typename C>
626 std::enable_if_t<is_condition_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
627  auto n = _graph.emplace_back(
628  nstd::in_place_type_t<Node::ConditionWork>{}, std::forward<C>(c)
629  );
630  return Task(n);
631 }
632 
633 #ifdef TF_ENABLE_CUDA
634 // Function: emplace
635 // emplaces a cudaflow task
636 template <typename C>
637 std::enable_if_t<is_cudaflow_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
638  auto n = _graph.emplace_back(
639  nstd::in_place_type_t<Node::cudaFlowWork>{}, std::forward<C>(c)
640  );
641  return Task(n);
642 }
643 #endif
644 
645 // Function: composed_of
647  auto node = _graph.emplace_back(
648  nstd::in_place_type_t<Node::ModuleWork>{}, &taskflow
649  );
650  return Task(node);
651 }
652 
653 // Function: placeholder
655  auto node = _graph.emplace_back();
656  return Task(node);
657 }
658 
659 // Procedure: _linearize
660 template <typename L>
661 void FlowBuilder::_linearize(L& keys) {
662 
663  auto itr = keys.begin();
664  auto end = keys.end();
665 
666  if(itr == end) {
667  return;
668  }
669 
670  auto nxt = itr;
671 
672  for(++nxt; nxt != end; ++nxt, ++itr) {
673  itr->_node->_precede(nxt->_node);
674  }
675 }
676 
677 // Procedure: linearize
679  _linearize(keys);
680 }
681 
682 // Procedure: linearize
684  _linearize(keys);
685 }
686 
687 // ----------------------------------------------------------------------------
688 
698 class Subflow : public FlowBuilder {
699 
700  friend class Executor;
701  friend class FlowBuilder;
702 
703  public:
704 
711  void join();
712 
719  void detach();
720 
726  bool joinable() const;
727 
728  private:
729 
730  Subflow(Executor&, Node*, Graph&);
731 
732  Executor& _executor;
733  Node* _parent;
734 
735  bool _joinable {true};
736 };
737 
738 // Constructor
739 inline Subflow::Subflow(Executor& executor, Node* parent, Graph& graph) :
740  FlowBuilder {graph},
741  _executor {executor},
742  _parent {parent} {
743 }
744 
745 // Function: joined
746 inline bool Subflow::joinable() const {
747  return _joinable;
748 }
749 
750 // ----------------------------------------------------------------------------
751 // Legacy code
752 // ----------------------------------------------------------------------------
753 
754 using SubflowBuilder = Subflow;
755 
756 } // end of namespace tf. ---------------------------------------------------
757 
758 
void linearize(std::vector< Task > &tasks)
adds adjacent dependency links to a linear list of tasks
Definition: flow_builder.hpp:678
bool joinable() const
queries if the subflow is joinable
Definition: flow_builder.hpp:746
Task for_each_index_guided(B &&beg, E &&end, S &&step, C &&callable, H &&chunk_size=1)
constructs an index-based parallel-for task using the guided partition algorithm. ...
Task transform_reduce_guided(B &&first, E &&last, T &init, BOP &&bop, UOP &&uop, H &&chunk_size=1)
constructs a STL-styled parallel transform-reduce task using the guided partition algorithm ...
Task transform_reduce_static(B &&first, E &&last, T &init, BOP &&bop, UOP &&uop, H &&chunk_size=0)
constructs a STL-styled parallel transform-reduce task using the static partition algorithm ...
Task for_each_guided(B &&beg, E &&end, C &&callable, H &&chunk_size=1)
constructs a STL-styled parallel-for task using the guided partition algorithm
Task transform_reduce_dynamic(B &&first, E &&last, T &init, BOP &&bop, UOP &&uop, H &&chunk_size=1)
constructs a STL-styled parallel transform-reduce task using the dynamic partition algorithm ...
Definition: error.hpp:9
Task for_each_static(B &&beg, E &&end, C &&callable, H &&chunk_size=0)
constructs a STL-styled parallel-for task using the dynamic partition algorithm
Graph & _graph
associated graph object
Definition: flow_builder.hpp:584
Task placeholder()
creates an empty task
Definition: flow_builder.hpp:654
void detach()
enables the subflow to detach from its parent task
Definition: executor.hpp:1393
Task reduce_dynamic(B &&first, E &&last, T &init, O &&bop, H &&chunk_size=1)
constructs a STL-styled parallel-reduce task using the dynamic partition algorithm ...
Task reduce_static(B &&first, E &&last, T &init, O &&bop, H &&chunk_size=0)
constructs a STL-styled parallel-reduce task using the static partition algorithm ...
Task for_each_index_static(B &&beg, E &&end, S &&step, C &&callable, H &&chunk_size=0)
constructs an index-based parallel-for task using the static partition algorithm. ...
Task for_each_index(B &&first, E &&last, S &&step, C &&callable)
constructs an index-based parallel-for task
std::enable_if_t< is_static_task_v< C >, Task > emplace(C &&callable)
creates a static task from a given callable object
Definition: flow_builder.hpp:606
Task composed_of(Taskflow &taskflow)
creates a module task from a taskflow
Definition: flow_builder.hpp:646
Task reduce(B &&first, E &&last, T &init, O &&bop)
constructs a STL-styled parallel-reduce task
main entry to create a task dependency graph
Definition: core/taskflow.hpp:18
Task for_each_dynamic(B &&beg, E &&end, C &&callable, H &&chunk_size=1)
constructs a STL-styled parallel-for task using the dynamic partition algorithm
FlowBuilder(Graph &graph)
constructs a flow builder with a graph
Definition: flow_builder.hpp:593
Task for_each(B &&first, E &&last, C &&callable)
constructs a STL-styled parallel-for task
building methods of a task dependency graph
Definition: flow_builder.hpp:13
handle to a node in a task dependency graph
Definition: task.hpp:115
Task for_each_index_dynamic(B &&beg, E &&end, S &&step, C &&callable, H &&chunk_size=1)
constructs an index-based parallel-for task using the dynamic partition algorithm.
Task transform_reduce(B &&first, E &&last, T &init, BOP &&bop, UOP &&uop)
constructs a STL-styled parallel transform-reduce task
execution interface for running a taskflow graph
Definition: executor.hpp:24
building methods of a subflow graph in dynamic tasking
Definition: flow_builder.hpp:698
void join()
enables the subflow to join its parent task
Definition: executor.hpp:1383
Task reduce_guided(B &&first, E &&last, T &init, O &&bop, H &&chunk_size=1)
constructs a STL-styled parallel-reduce task using the guided partition algorithm ...