Taskflow  3.2.0-Master-Branch
Loading...
Searching...
No Matches
Runtime Tasking

Taskflow allows you to interact with the scheduling runtime from the execution context of a runtime task. Runtime tasking is mostly used for designing specialized parallel algorithms that go beyond the default scheduling rules of taskflows.

Create a Runtime Task

A runtime task is a callable that takes a reference to a tf::Runtime object in its argument. A tf::Runtime object is created by the running executor and contains several methods for users to interact with the scheduling runtime. For instance, the following code creates a runtime task to forcefully schedule a conditioned task that would never happens:

tf::Task A, B, C, D;
std::tie(A, B, C, D) = taskflow.emplace(
[] () { return 0; },
[&C] (tf::Runtime& rt) { // C must be captured by reference
std::cout << "B\n";
rt.schedule(C);
},
[] () { std::cout << "C\n"; },
[] () { std::cout << "D\n"; }
);
A.precede(B, C, D);
executor.run(taskflow).wait();
class to create a runtime object used by a runtime task
Definition graph.hpp:150
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
T tie(T... args)
dot_runtime_task_1.png

When the condition task A completes and returns 0, the scheduler moves on to the runtime task B. Under the normal circumstance, tasks C and D will not run because their conditional dependencies never happen. This can be broken by forcefully scheduling C or/and D via a runtime task that resides in the same graph. Here, the runtime task B call tf::Runtime::schedule(tf::Task) to run task C even though the weak dependency between A and C will never happen based on the graph structure itself. As a result, we will see both B and C in the output:

B # B is a runtime task to schedule C out of its dependency constraint
C
Attention
You should only schedule an active task from a runtime task. An active task is a task in a running taskflow. The task may or may not be running, and scheduling that task will immediately put the task into the task queue of the worker that is running the runtime task.

Acquire the Running Executor

You can acquire the reference to the running executor using tf::Runtime::executor(). The running executor of a runtime task is the executor that runs the parent taskflow of that runtime task.

tf::Executor executor;
tf::Taskflow taskflow;
taskflow.emplace([&](tf::Runtime& rt){
assert(&(rt.executor()) == &executor);
});
executor.run(taskflow).wait();
class to create an executor for running a taskflow graph
Definition executor.hpp:50
tf::Future< void > run(Taskflow &taskflow)
runs a taskflow once
Definition executor.hpp:1573
Task emplace(C &&callable)
creates a static task
Definition flow_builder.hpp:742
Executor & executor()
obtains the running executor
Definition graph.hpp:233
class to create a taskflow object
Definition core/taskflow.hpp:73