Taskflow  3.2.0-Master-Branch
Loading...
Searching...
No Matches
tf::Subflow Class Reference

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

#include <flow_builder.hpp>

Inheritance diagram for tf::Subflow:
Collaboration diagram for tf::Subflow:

Public Member Functions

void join ()
 enables the subflow to join its parent task
 
void detach ()
 enables the subflow to detach from its parent task
 
void reset ()
 resets the subflow to a clean graph of joinable state
 
bool joinable () const noexcept
 queries if the subflow is joinable
 
template<typename F , typename... ArgsT>
auto async (F &&f, ArgsT &&... args)
 runs a given function asynchronously
 
template<typename F , typename... ArgsT>
auto named_async (const std::string &name, F &&f, ArgsT &&... args)
 runs the given function asynchronously and assigns the task a name
 
template<typename F , typename... ArgsT>
void silent_async (F &&f, ArgsT &&... args)
 similar to tf::Subflow::async but does not return a future object
 
template<typename F , typename... ArgsT>
void named_silent_async (const std::string &name, F &&f, ArgsT &&... args)
 similar to tf::Subflow::named_async but does not return a future object
 
Executorexecutor ()
 returns the executor that runs this subflow
 
- Public Member Functions inherited from tf::FlowBuilder
 FlowBuilder (Graph &graph)
 constructs a flow builder with a graph
 
template<typename C , std::enable_if_t< is_static_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a static task
 
template<typename C , std::enable_if_t< is_dynamic_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a dynamic task
 
template<typename C , std::enable_if_t< is_condition_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a condition task
 
template<typename C , std::enable_if_t< is_multi_condition_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a multi-condition task
 
template<typename... C, std::enable_if_t<(sizeof...(C)>1), void > * = nullptr>
auto emplace (C &&... callables)
 creates multiple tasks from a list of callable objects
 
void erase (Task task)
 removes a task from a taskflow
 
template<typename T >
Task composed_of (T &object)
 creates a module task for the target object
 
Task placeholder ()
 creates a placeholder task
 
template<typename C , std::enable_if_t< is_cudaflow_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a cudaFlow task on the caller's GPU device context
 
template<typename C , typename D , std::enable_if_t< is_cudaflow_task_v< C >, void > * = nullptr>
Task emplace_on (C &&callable, D &&device)
 creates a cudaFlow task on the given device
 
template<typename C , std::enable_if_t< is_syclflow_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a syclFlow task on the default queue
 
template<typename C , typename Q , std::enable_if_t< is_syclflow_task_v< C >, void > * = nullptr>
Task emplace_on (C &&callable, Q &&queue)
 creates a syclFlow task on the given queue
 
template<typename C , std::enable_if_t< is_runtime_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a runtime 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<typename B , typename E , typename C >
Task for_each (B first, E last, C callable)
 constructs a STL-styled parallel-for task
 
template<typename B , typename E , typename S , typename C >
Task for_each_index (B first, E last, S step, C callable)
 constructs a parallel-transform task
 
template<typename B , typename E , typename O , typename C >
Task transform (B first1, E last1, O d_first, C c)
 constructs a parallel-transform task
 
template<typename B1 , typename E1 , typename B2 , typename O , typename C >
Task transform (B1 first1, E1 last1, B2 first2, O d_first, C c)
 constructs a parallel-transform task
 
template<typename B , typename E , typename T , typename O >
Task reduce (B first, E last, T &init, O bop)
 constructs a STL-styled parallel-reduce task
 
template<typename B , typename E , typename T , typename BOP , typename UOP >
Task transform_reduce (B first, E last, T &init, BOP bop, UOP uop)
 constructs a STL-styled parallel transform-reduce task
 
template<typename B , typename E , typename C >
Task sort (B first, E last, C cmp)
 constructs a dynamic task to perform STL-styled parallel sort
 
template<typename B , typename 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
 

Friends

class Executor
 
class FlowBuilder
 
class Runtime
 

Additional Inherited Members

- Protected Attributes inherited from tf::FlowBuilder
Graph_graph
 associated graph object
 

Detailed Description

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

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 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
Task emplace(C &&callable)
creates a static task
Definition flow_builder.hpp:742
class to construct a subflow graph from the execution of a dynamic task
Definition flow_builder.hpp:889
class to create a task handle over a node in a taskflow graph
Definition task.hpp:187
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition task.hpp:420

Member Function Documentation

◆ async()

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

runs a given function asynchronously

Template Parameters
Fcallable type
ArgsTparameter types
Parameters
fcallable object to call
argsparameters to pass to the callable
Returns
a tf::Future that will holds the result of the execution

The method creates an asynchronous task to launch the given function on the given arguments. 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);
});
void join()
enables the subflow to join its parent task
Definition executor.hpp:1826
auto async(F &&f, ArgsT &&... args)
runs a given function asynchronously
Definition executor.hpp:1908

This method is thread-safe and can be called by multiple tasks in the subflow at the same time.

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

◆ detach()

void tf::Subflow::detach ( )
inline

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.

taskflow.emplace([](tf::Subflow& sf){
sf.emplace([](){});
sf.detach();
});
void detach()
enables the subflow to detach from its parent task
Definition executor.hpp:1839

Only the worker that spawns this subflow can detach it.

◆ join()

void tf::Subflow::join ( )
inline

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
});

Only the worker that spawns this subflow can join it.

◆ joinable()

bool tf::Subflow::joinable ( ) const
inlinenoexcept

queries if the subflow is joinable

This member function queries if the subflow is joinable. When a subflow is joined or detached, 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
});
bool joinable() const noexcept
queries if the subflow is joinable
Definition flow_builder.hpp:1112

◆ named_async()

template<typename F , typename... ArgsT>
auto tf::Subflow::named_async ( const std::string name,
F &&  f,
ArgsT &&...  args 
)

runs the given function asynchronously and assigns the task a name

Template Parameters
Fcallable type
ArgsTparameter types
Parameters
namename of the asynchronous task
fcallable object to call
argsparameters to pass to the callable
Returns
a tf::Future that will holds the result of the execution

The method creates a named asynchronous task to launch the given function on the given arguments. The difference from 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("name", [&](){ counter++; });
}
sf.join();
assert(counter == 100);
});

This method is thread-safe and can be called by multiple tasks in the subflow at the same time.

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

◆ named_silent_async()

template<typename F , typename... ArgsT>
void tf::Subflow::named_silent_async ( const std::string name,
F &&  f,
ArgsT &&...  args 
)

similar to tf::Subflow::named_async but does not return a future object

This member function is more efficient than tf::Subflow::named_async and is encouraged to use when there is no data returned.

taskflow.empalce([&](tf::Subflow& sf){
for(int i=0; i<100; i++) {
sf.named_silent_async("name", [&](){ counter++; });
}
sf.join();
assert(counter == 100);
});
void named_silent_async(const std::string &name, F &&f, ArgsT &&... args)
similar to tf::Subflow::named_async but does not return a future object
Definition executor.hpp:1936

This member function is thread-safe.

◆ reset()

void tf::Subflow::reset ( )
inline

resets the subflow to a clean graph of joinable state

Resetting a subflow will first clear the underlying task dependency graphs and then change the subflow to a joinable state.

◆ silent_async()

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

similar to tf::Subflow::async but does not return a future object

This member function is more efficient than tf::Subflow::async and is encouraged to use when there is no data returned.

taskflow.empalce([&](tf::Subflow& sf){
for(int i=0; i<100; i++) {
sf.silent_async([&](){ counter++; });
}
sf.join();
assert(counter == 100);
});
void silent_async(F &&f, ArgsT &&... args)
similar to tf::Subflow::async but does not return a future object
Definition executor.hpp:1944

This member function is thread-safe.


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