Taskflow
2.4-master-branch
|
This chapter demonstrates how to create a static task dependency graph. Static tasking captures the static parallel structure of a decomposition and is defined only by the program itself. It has a flat task hierarchy and cannot spawn new tasks from a running dependency graph.
A task in Taskflow is a callable object for which the operation std::invoke is applicable. It can be either a functor, a lambda expression, a bind expression, or a class objects with operator()
overloaded. All tasks are created from tf::Taskflow, the class that manages a task dependency graph. Taskflow provides two methods, tf::Taskflow::placeholder and tf::Taskflow::emplace to create a task.
Debrief:
Each time you create a task, the taskflow object creates a node in the task graph and returns a task handle of type tf::Task. A task handle is a lightweight object that wraps up a particular node in a graph and provides a set of methods for you to assign different attributes to the task such as adding dependencies, naming, and assigning a new work.
Debrief:
Taskflow uses general-purpose polymorphic function wrapper, std::function, to store and invoke a callable in a task. You need to follow its contract to create a task.
You can dump a taskflow to a DOT format and visualize the graph using free online tools such as GraphvizOnline and WebGraphviz.
Debrief:
This example demonstrates how to modify a task's attributes using methods defined in the task handler.
The output of this program looks like the following:
Debrief:
You can change the name and work of a task at anytime before running the graph. The later assignment overwrites the previous values.
You can iterate the successor list and the dependent list of a task by using tf::Task::for_each_successor and tf::Task::for_each_dependent, respectively. Each method takes a lambda and applies it to a successor or a dependent being traversed.
A task lives with its graph and belongs to only a graph at a time, and is not destroyed until the graph gets cleaned up. The lifetime of a task refers to the user-given callable object, including captured values. As long as the graph is alive, all the associated tasks exist. It is your responsibility to keep tasks and graph alive during their execution.