tf::Subflow class

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

Contents

By default, a subflow automatically joins its parent node. You may explicitly join or detach a subflow by calling tf::Subflow::join or tf::Subflow::detach, respectively. 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 regular 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 

Base classes

class FlowBuilder
building methods of a task dependency graph

Public functions

void join()
enables the subflow to join its parent task
void detach()
enables the subflow to detach from its parent task
auto joinable() const -> bool
queries if the subflow is joinable
template<typename F, typename... ArgsT>
auto async(F&& f, ArgsT && ... args) -> auto
runs a given function asynchronously
template<typename F, typename... ArgsT>
void silent_async(F&& f, ArgsT && ... args)
similar to tf::Subflow::async but did not return a future object

Function documentation

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.

void tf::Subflow::detach()

enables the subflow to detach from its parent task

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

bool tf::Subflow::joinable() const

queries if the subflow is joinable

When a subflow is joined or detached, it becomes not joinable.

template<typename F, typename... ArgsT>
auto tf::Subflow::async(F&& f, ArgsT && ... args)

runs a given function asynchronously

Template parameters
F callable type
ArgsT parameter types
Parameters
f callable object to call
args parameters to pass to the callable
Returns a tf::Future that will holds the result of the execution

This method is thread-safe and can be called by multiple tasks in the subflow at the same time. The difference to tf::Executor::async is that the created asynchronous task pertains to the subflow. When the subflow joins, all asynchronous tasks created from the subflow are guaranteed to finish before the join. For example:

std::atomic<int> counter(0);
taskflow.empalce([&](tf::Subflow& sf){
  for(int i=0; i<100; i++) {
    sf.async([&](){ counter++; });
  }
  sf.join();
  assert(counter == 100);
});

You cannot create asynchronous tasks from a detached subflow. Doing this results in undefined behavior.