| Taskflow: A General-purpose Task-parallel Programming System

Loading...
Searching...
No Matches
Public Member Functions | Friends | List of all members
tf::Subflow Class Reference

class to construct a subflow graph from the execution of a dynamic task More...

`#include <taskflow/core/flow_builder.hpp>`

Inheritance diagram for tf::Subflow:
[legend]
Collaboration diagram for tf::Subflow:
[legend]

## Public Member Functions
void | join ()
| enables the subflow to join its parent task
bool | joinable () const noexcept
| queries if the subflow is joinable
Executor & | executor () noexcept
| acquires the associated executor
Graph & | graph ()
| acquires the associated graph
void | retain (bool flag) noexcept
| specifies whether to keep the subflow after it is joined
bool | retain () const
| queries if the subflow will be retained after it is joined
Public Member Functions inherited from tf::FlowBuilder
| FlowBuilder (Graph &graph)
| constructs a flow builder with a graph
template<StaticTaskLike C>
Task | emplace (C &&callable)
| creates a static task
template<RuntimeTaskLike C>
Task | emplace (C &&callable)
| creates a runtime task
template<SubflowTaskLike C>
Task | emplace (C &&callable)
| creates a dynamic task
template<ConditionTaskLike C>
Task | emplace (C &&callable)
| creates a condition task
template<MultiConditionTaskLike C>
Task | emplace (C &&callable)
| creates a multi-condition task
template<typename... C> requires (sizeof...(C) > 1)
auto | emplace (C &&... callables)
| creates multiple tasks from a list of callable objects
void | erase (Task task)
| removes a task from a taskflow
template<GraphLike T>
Task | composed_of (T &object)
| creates a module task for the target object
Task | adopt (Graph &&graph)
| creates a module task from a graph by taking over its ownership
template<GraphLike T>
Task | emplace (T &object)
| creates a module task for the target object (convenience overload of tf::FlowBuilder::composed_of)
Task | emplace (Graph &&graph)
| creates a module task from a graph by taking over its ownership (convenience overload of tf::FlowBuilder::adopt)
Task | placeholder ()
| creates a placeholder task
void | linearize (std::vector< Task > &tasks)
| adds adjacent dependency links to a linear list of tasks
void | linearize (std::initializer_list< Task > tasks)
| adds adjacent dependency links to a linear list of tasks
template<InputIteratorLike B, InputIteratorLike E, typename C , PartitionerLike P = DefaultPartitioner> requires UnaryOperationLike<C, std::decay_t<std::unwrap_ref_decay_t<B>>>
Task | for_each (B first, E last, C callable, P part=P())
| constructs an STL-styled parallel-for task
template<typename B , typename E , typename S , typename C , PartitionerLike P = DefaultPartitioner>
Task | for_each_index (B first, E last, S step, C callable, P part=P())
| constructs an index-based parallel-for task
template<IndexRangesLike R, typename C , PartitionerLike P = DefaultPartitioner>
Task | for_each_by_index (R range, C callable, P part=P())
| constructs a parallel-for task over a one- or multi-dimensional index range
template<InputIteratorLike B, InputIteratorLike E, typename O , typename C , PartitionerLike P = DefaultPartitioner> requires UnaryTransformLike< C, std::decay_t<std::unwrap_ref_decay_t<B>>, std::decay_t<std::unwrap_ref_decay_t<O>> >
Task | transform (B first1, E last1, O d_first, C c, P part=P())
| constructs a parallel-transform task
template<InputIteratorLike B1, InputIteratorLike E1, InputIteratorLike B2, typename O , typename C , PartitionerLike P = DefaultPartitioner> requires BinaryTransformLike< C, std::decay_t<std::unwrap_ref_decay_t<B1>>, std::decay_t<std::unwrap_ref_decay_t<B2>>, std::decay_t<std::unwrap_ref_decay_t<O>> >
Task | transform (B1 first1, E1 last1, B2 first2, O d_first, C c, P part=P())
| constructs a parallel-transform task
template<InputIteratorLike B, InputIteratorLike E, typename T , typename O , PartitionerLike P = DefaultPartitioner>
Task | reduce (B first, E last, T &init, O bop, P part=P())
| constructs an STL-styled parallel-reduction task
template<IndexRanges1DLike R, typename T , typename L , typename G , PartitionerLike P = DefaultPartitioner>
Task | reduce_by_index (R range, T &init, L lop, G gop, P part=P())
| constructs an index range-based parallel-reduction task
template<InputIteratorLike B, InputIteratorLike E, typename T , typename BOP , typename UOP , PartitionerLike P = DefaultPartitioner>
Task | transform_reduce (B first, E last, T &init, BOP bop, UOP uop, P part=P())
| constructs an STL-styled parallel transform-reduce task
template<InputIteratorLike B1, InputIteratorLike E1, InputIteratorLike B2, typename T , typename BOP_R , typename BOP_T , PartitionerLike P = DefaultPartitioner> requires BinaryOperationLike< BOP_T, std::decay_t<std::unwrap_ref_decay_t<B1>>, std::decay_t<std::unwrap_ref_decay_t<B2>> >
Task | transform_reduce (B1 first1, E1 last1, B2 first2, T &init, BOP_R bop_r, BOP_T bop_t, P part=P())
| constructs an STL-styled parallel transform-reduce task
template<InputIteratorLike B, InputIteratorLike E, typename D , typename BOP >
Task | inclusive_scan (B first, E last, D d_first, BOP bop)
| creates an STL-styled parallel inclusive-scan task
template<InputIteratorLike B, InputIteratorLike E, typename D , typename BOP , typename T >
Task | inclusive_scan (B first, E last, D d_first, BOP bop, T init)
| creates an STL-styled parallel inclusive-scan task with an initial value
template<InputIteratorLike B, InputIteratorLike E, typename D , typename T , typename BOP >
Task | exclusive_scan (B first, E last, D d_first, T init, BOP bop)
| creates an STL-styled parallel exclusive-scan task
template<InputIteratorLike B, InputIteratorLike E, typename D , typename BOP , typename UOP >
Task | transform_inclusive_scan (B first, E last, D d_first, BOP bop, UOP uop)
| creates an STL-styled parallel transform-inclusive scan task
template<InputIteratorLike B, InputIteratorLike E, typename D , typename BOP , typename UOP , typename T >
Task | transform_inclusive_scan (B first, E last, D d_first, BOP bop, UOP uop, T init)
| creates an STL-styled parallel transform-inclusive scan task
template<InputIteratorLike B, InputIteratorLike E, typename D , typename T , typename BOP , typename UOP >
Task | transform_exclusive_scan (B first, E last, D d_first, T init, BOP bop, UOP uop)
| creates an STL-styled parallel transform-exclusive scan task
template<InputIteratorLike B, InputIteratorLike E, typename T , typename UOP , PartitionerLike P = DefaultPartitioner>
Task | find_if (B first, E last, T &result, UOP predicate, P part=P())
| constructs a task to perform STL-styled find-if algorithm
template<InputIteratorLike B, InputIteratorLike E, typename T , typename UOP , PartitionerLike P = DefaultPartitioner>
Task | find_if_not (B first, E last, T &result, UOP predicate, P part=P())
| constructs a task to perform STL-styled find-if-not algorithm
template<InputIteratorLike B, InputIteratorLike E, typename T , typename C , PartitionerLike P>
Task | min_element (B first, E last, T &result, C comp, P part)
| constructs a task to perform STL-styled min-element algorithm
template<InputIteratorLike B, InputIteratorLike E, typename T , typename C , PartitionerLike P>
Task | max_element (B first, E last, T &result, C comp, P part)
| constructs a task to perform STL-styled max-element algorithm
template<InputIteratorLike B, InputIteratorLike E, typename C >
Task | sort (B first, E last, C cmp)
| constructs a dynamic task to perform STL-styled parallel sort
template<InputIteratorLike B, InputIteratorLike E>
Task | sort (B first, E last)
| constructs a dynamic task to perform STL-styled parallel sort using the `std::less<T>` comparator, where `T` is the element type
template<InputIteratorLike B1, InputIteratorLike E1, InputIteratorLike B2, InputIteratorLike E2, typename O >
Task | merge (B1 first1, E1 last1, B2 first2, E2 last2, O d_first)
| merges two sorted ranges into a single sorted output using the `std::less` comparator
template<InputIteratorLike B1, InputIteratorLike E1, InputIteratorLike B2, InputIteratorLike E2, typename O , typename C >
Task | merge (B1 first1, E1 last1, B2 first2, E2 last2, O d_first, C cmp)
| merges two sorted ranges into a single sorted output using a custom comparator
template<InputIteratorLike B, InputIteratorLike E, typename V , PartitionerLike P = DefaultPartitioner>
Task | fill (B first, E last, V value, P part=P())
| fills a range with a given value in parallel
template<InputIteratorLike B, std::integral C, typename V , PartitionerLike P = DefaultPartitioner>
Task | fill_n (B first, C count, V value, P part=P())
| fills N elements with a given value in parallel
template<InputIteratorLike B, InputIteratorLike E, typename G , PartitionerLike P = DefaultPartitioner>
Task | generate (B first, E last, G gen, P part=P())
| generates values into a range in parallel using a callable
template<InputIteratorLike B, std::integral C, typename G , PartitionerLike P = DefaultPartitioner>
Task | generate_n (B first, C count, G gen, P part=P())
| generates N values into a range in parallel using a callable

## Friends
class | Executor
class | FlowBuilder

## Detailed Description

class to construct a subflow graph from the execution of a dynamic task

tf::Subflow is spawned from the execution of a task to dynamically manage a child graph that may depend on runtime variables. You can explicitly join a subflow by calling tf::Subflow::join, respectively. By default, the Taskflow runtime will implicitly join a subflow it is is joinable.

The following example creates a taskflow graph that spawns a subflow from the execution of task `B`, and the subflow contains three tasks, `B1`, `B2`, and `B3`, where `B3` runs after `B1` and `B2`.

// create three static tasks
tf::Task A = taskflow.emplace([](){}).name("A");
tf::Task C = taskflow.emplace([](){}).name("C");
tf::Task D = taskflow.emplace([](){}).name("D");
// create a subflow graph (dynamic tasking)
tf::Task B = taskflow.emplace([] (tf::Subflow& subflow) {
tf::Task B1 = subflow.emplace([](){}).name("B1");
tf::Task B2 = subflow.emplace([](){}).name("B2");
tf::Task B3 = subflow.emplace([](){}).name("B3");
B1.precede(B3);
B2.precede(B3);
}).name("B");
A.precede(B); // B runs after A
A.precede(C); // C runs after A
B.precede(D); // D runs after B
C.precede(D); // D runs after C
tf::FlowBuilder::emplace
Task emplace(C &&callable)
creates a static task
Definition flow_builder.hpp:1738
tf::Subflow
class to construct a subflow graph from the execution of a dynamic task
Definition flow_builder.hpp:1913
tf::Task
class to create a task handle over a taskflow node
Definition task.hpp:569
tf::Task::precede
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition task.hpp:1258

## Member Function Documentation

## ◆ join()

void tf::Subflow::join | ( |  | ) |

enables the subflow to join its parent task

Performs an immediate action to join the subflow. Once the subflow is joined, it is considered finished and you may not modify the subflow anymore.

taskflow.emplace([](tf::Subflow& sf){
sf.emplace([](){});
sf.join(); // join the subflow of one task
});
tf::Subflow::join
void join()
enables the subflow to join its parent task

Only the worker that spawns this subflow can join it.

## ◆ joinable()

bool tf::Subflow::joinable | ( |  | ) | const
| inline noexcept

queries if the subflow is joinable

This member function queries if the subflow is joinable. When a subflow is joined, it becomes not joinable.

taskflow.emplace([](tf::Subflow& sf){
sf.emplace([](){});
std::cout << sf.joinable() << '\n'; // true
sf.join();
std::cout << sf.joinable() << '\n'; // false
});
tf::Subflow::joinable
bool joinable() const noexcept
queries if the subflow is joinable
Definition flow_builder.hpp:2012

## ◆ retain() [1/2]

bool tf::Subflow::retain | ( |  | ) | const
| inline

queries if the subflow will be retained after it is joined

Returns
  `true` if the subflow will be retained after it is joined; `false` otherwise

By default, the runtime automatically clears a spawned subflow once it is joined. Users can disable this before by explicitly calling tf::Subflow::retain.

## ◆ retain() [2/2]

void tf::Subflow::retain | ( | bool | flag | ) |
| inline noexcept

specifies whether to keep the subflow after it is joined

Parameters

  flag | `true` to retain the subflow after it is joined; `false` to discard it

By default, the runtime automatically clears a spawned subflow once it is joined. Setting this flag to `true` allows the application to retain the subflow's structure for post-execution analysis like visualization.

The documentation for this class was generated from the following file:

- taskflow/core/flow_builder.hpp