Cpp-Taskflow
2.1.0
|
In this chapter, we demonstrate the basic construct of a task dependency graph - tf::Task.
A task in Cpp-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. Cpp-Taskflow provides two methods, tf::Taskflow::placeholder and tf::Taskflow::emplace to create a task.
Debrief:
Each time you create a task, including an empty one, the taskflow object adds a node to the present graph and returns a task handle of type 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:
Cpp-Taskflow uses the general-purpose polymorphic function wrapper std::function to store and invoke any callable target in a task. You need to follow its contract to create a task. For instance, the callable object must be copy constructible.
Cpp-Taskflow uses C++ structured binding coupled with tuple to make the creation of tasks simple. The mthod tf::Taskflow::emplace accepts a arbitrary number of callable objects to create multiple tasks at one time.
A task lives with its graph, and is not destroyed until its parent graph gets cleaned up. A task belongs to only a graph at a time. The lifetime of a task mostly refers to the user-given callable object, including captured values. As long as the graph is alive, all the associated tasks remain their existence. We recommend the users to read Lifetime of a Graph.
The example below demonstrates how to reuse task handles to create two task dependency graphs.
Debrief:
Notice that trying to modify a task in a dispatched graph results in undefined behavior. For examples, starting from Line 21, you should not modify any tasks but assign them to new targets (Line 23-28).
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 dispatching the graph. The later assignment overwrites the previous values. Only the latest information will be used.