tf::Taskflow
tf::FlowBuilder
taskflow/core/taskflow.hpp
tf::Taskflow::Dumper
class friend class Topology Topology Topology
class friend class Executor Executor Executor
class friend class FlowBuilder FlowBuilder FlowBuilder
std::mutex std::mutex tf::Taskflow::_mutex _mutex
std::string std::string tf::Taskflow::_name _name
Graph Graph tf::Taskflow::_graph _graph
std::queue< std::shared_ptr< Topology > > std::queue<std::shared_ptr<Topology> > tf::Taskflow::_topologies _topologies
std::optional< std::list< Taskflow >::iterator > std::optional<std::list<Taskflow>::iterator> tf::Taskflow::_satellite _satellite
tf::Taskflow::Taskflow
(const std::string &name)
Taskflow
const std::string & name

constructs a taskflow with the given name

    tf::Taskflowtaskflow("MyTaskflow");
    std::cout<<taskflow.name();//"MyTaskflow"

tf::Taskflow::Taskflow
()
Taskflow

constructs a taskflow

tf::Taskflow::Taskflow
(Taskflow &&rhs)
Taskflow
Taskflow && rhs

constructs a taskflow from a moved taskflow

Constructing a taskflow `taskflow1` from a moved taskflow `taskflow2` will migrate the graph of `taskflow2` to `taskflow1`. After the move, `taskflow2` will become empty.

    tf::Taskflowtaskflow1(std::move(taskflow2));
    assert(taskflow2.empty());

Notice that `taskflow2` should not be running in an executor during the move operation, or the behavior is undefined.

Taskflow & Taskflow & tf::Taskflow::operator= (Taskflow &&rhs) operator= Taskflow && rhs

move assignment operator

Moving a taskflow `taskflow2` to another taskflow `taskflow1` will destroy the existing graph of `taskflow1` and assign it the graph of `taskflow2`. After the move, `taskflow2` will become empty.

    taskflow1=std::move(taskflow2);
    assert(taskflow2.empty());

Notice that both `taskflow1` and `taskflow2` should not be running in an executor during the move operation, or the behavior is undefined.

tf::Taskflow::~Taskflow
()=default
~Taskflow

default destructor

When the destructor is called, all tasks and their associated data (e.g., captured data) will be destroyed. It is your responsibility to ensure all submitted execution of this taskflow have completed before destroying it. For instance, the following code results in undefined behavior since the executor may still be running the taskflow while it is destroyed after the block.

    {
    tf::Taskflowtaskflow;
    executor.run(taskflow);
    }

To fix the problem, we must wait for the execution to complete before destroying the taskflow.

    {
    tf::Taskflowtaskflow;
    executor.run(taskflow).wait();
    }

void void tf::Taskflow::dump (std::ostream &ostream) const dump std::ostream & ostream

dumps the taskflow to a DOT format through a std::ostream target

    taskflow.dump(std::cout);//dumpthegraphtothestandardoutput

    std::ofstreamofs("output.dot");
    taskflow.dump(ofs);//dumpthegraphtothefileoutput.dot

For dynamically spawned tasks, such as module tasks, subflow tasks, and GPU tasks, you need to run the taskflow first before you can dump the entire graph.

    tf::Taskparent=taskflow.emplace([](tf::Subflowsf){
    sf.emplace([](){std::cout<<"child\n";});
    });
    taskflow.dump(std::cout);//thisdumpsonlytheparenttasks
    executor.run(taskflow).wait();
    taskflow.dump(std::cout);//thisdumpsbothparentandchildtasks

std::string std::string tf::Taskflow::dump () const dump

dumps the taskflow to a std::string of DOT format

This method is similar to tf::Taskflow::dump(std::ostream& ostream), but returning a string of the graph in DOT format.

size_t size_t tf::Taskflow::num_tasks () const num_tasks

queries the number of tasks

bool bool tf::Taskflow::empty () const empty

queries the emptiness of the taskflow

An empty taskflow has no tasks. That is the return of tf::Taskflow::num_tasks is zero.

void void tf::Taskflow::name (const std::string &) name const std::string & name

assigns a name to the taskflow

    taskflow.name("assignanothername");

const std::string & const std::string & tf::Taskflow::name () const name

queries the name of the taskflow

    std::cout<<"mynameis:"<<taskflow.name();

void void tf::Taskflow::clear () clear

clears the associated task dependency graph

When you clear a taskflow, all tasks and their associated data (e.g., captured data in task callables) will be destroyed. The behavior of clearing a running taskflow is undefined.

typename V
void void tf::Taskflow::for_each_task (V &&visitor) const for_each_task V && visitor

applies a visitor to each task in the taskflow

A visitor is a callable that takes an argument of type tf::Task and returns nothing. The following example iterates each task in a taskflow and prints its name:

    taskflow.for_each_task([](tf::Tasktask){
    std::cout<<task.name()<<'\n';
    });

void void tf::Taskflow::remove_dependency (Task from, Task to) remove_dependency Task from Task to

removes dependencies that go from task `from` to task `to`

from

from task (dependent)

to

to task (successor)

    tf::Taskflowtaskflow;
    autoa=taskflow.placeholder().name("a");
    autob=taskflow.placeholder().name("b");
    autoc=taskflow.placeholder().name("c");
    autod=taskflow.placeholder().name("d");

    a.precede(b,c,d);
    assert(a.num_successors()==3);
    assert(b.num_dependents()==1);
    assert(c.num_dependents()==1);
    assert(d.num_dependents()==1);

    taskflow.remove_dependency(a,b);
    assert(a.num_successors()==2);
    assert(b.num_dependents()==0);

Graph & Graph & tf::Taskflow::graph () graph

returns a reference to the underlying graph object

A graph object (of type tf::Graph) is the ultimate storage for the task dependency graph and should only be used as an opaque data structure to interact with the executor (e.g., composition).

void void tf::Taskflow::_dump (std::ostream &, const Graph *) const _dump std::ostream & os const Graph * top
void void tf::Taskflow::_dump (std::ostream &, const Node *, Dumper &) const _dump std::ostream & os const Node * node Dumper & dumper
void void tf::Taskflow::_dump (std::ostream &, const Graph *, Dumper &) const _dump std::ostream & os const Graph * graph Dumper & dumper

class to create a taskflow object

A taskflow manages a task dependency graph where each task represents a callable object (e.g., lambda, std::function) and an edge represents a dependency between two tasks. A task is one of the following types:

1. static task : the callable constructible from `std::function<void()>`

2. subflow task : the callable constructible from `std::function<void(tf::Subflow&)>`

3. condition task : the callable constructible from `std::function<int()>`

4. multi-condition task: the callable constructible from `std::function<tf::SmallVector<int>()>`

5. module task : the task constructed from tf::Taskflow::composed_of `std::function<void(tf::Runtime&)>`

Each task is a basic computation unit and is run by one worker thread from an executor. The following example creates a simple taskflow graph of four static tasks, `A`, `B`, `C`, and `D`, where `A` runs before `B` and `C` and `D` runs after `B` and `C`.

    tf::Executorexecutor;
    tf::Taskflowtaskflow("simple");

    tf::TaskA=taskflow.emplace([](){std::cout<<"TaskA\n";});
    tf::TaskB=taskflow.emplace([](){std::cout<<"TaskB\n";});
    tf::TaskC=taskflow.emplace([](){std::cout<<"TaskC\n";});
    tf::TaskD=taskflow.emplace([](){std::cout<<"TaskD\n";});

    A.precede(B,C);//ArunsbeforeBandC
    D.succeed(B,C);//DrunsafterBandC

    executor.run(taskflow).wait();

The taskflow object itself is NOT thread-safe. You should not modifying the graph while it is running, such as adding new tasks, adding new dependencies, and moving the taskflow to another. To minimize the overhead of task creation, our runtime leverages a global object pool to recycle tasks in a thread-safe manner.

Please refer to Cookbook to learn more about each task type and how to submit a taskflow to an executor.

tf::FlowBuilder
tf::Taskflow
tf::FlowBuilder
_graph
tf::Graph
tf::Taskflow
- tf::Taskflow
  _dump
- tf::Taskflow
  _dump
- tf::Taskflow
  _dump
- tf::Taskflow
  _graph
- tf::Taskflow
  _mutex
- tf::Taskflow
  _name
- tf::Taskflow
  _satellite
- tf::Taskflow
  _topologies
- tf::Taskflow
  clear
- tf::Taskflow
  composed_of
- tf::Taskflow
  dump
- tf::Taskflow
  dump
- tf::Taskflow
  emplace
- tf::Taskflow
  emplace
- tf::Taskflow
  emplace
- tf::Taskflow
  emplace
- tf::Taskflow
  emplace
- tf::Taskflow
  empty
- tf::Taskflow
  erase
- tf::Taskflow
  exclusive_scan
- tf::Taskflow
  Executor
- tf::Taskflow
  find_if
- tf::Taskflow
  find_if_not
- tf::Taskflow
  FlowBuilder
- tf::Taskflow
  FlowBuilder
- tf::Taskflow
  for_each
- tf::Taskflow
  for_each_index
- tf::Taskflow
  for_each_task
- tf::Taskflow
  graph
- tf::Taskflow
  inclusive_scan
- tf::Taskflow
  inclusive_scan
- tf::Taskflow
  linearize
- tf::Taskflow
  linearize
- tf::Taskflow
  max_element
- tf::Taskflow
  min_element
- tf::Taskflow
  name
- tf::Taskflow
  name
- tf::Taskflow
  num_tasks
- tf::Taskflow
  operator=
- tf::Taskflow
  placeholder
- tf::Taskflow
  reduce
- tf::Taskflow
  remove_dependency
- tf::Taskflow
  sort
- tf::Taskflow
  sort
- tf::Taskflow
  Taskflow
- tf::Taskflow
  Taskflow
- tf::Taskflow
  Taskflow
- tf::Taskflow
  Topology
- tf::Taskflow
  transform
- tf::Taskflow
  transform
- tf::Taskflow
  transform_exclusive_scan
- tf::Taskflow
  transform_inclusive_scan
- tf::Taskflow
  transform_inclusive_scan
- tf::Taskflow
  transform_reduce
- tf::Taskflow
  transform_reduce
- tf::Taskflow
  ~Taskflow