tf::Runtime class

class to create a runtime object used by a runtime task

Contents

A runtime object is used by a runtime task for users to interact with the scheduling runtime, such as scheduling an active task and spawning a subflow.

taskflow.emplace([](tf::Runtime& rt){
  rt.run([](tf::Subflow& sf){
    tf::Task A = sf.emplace([](){});
    tf::Task B = sf.emplace([](){});
    A.precede(B);
  });
});

A runtime task is associated with an executor and a worker that runs the runtime task.

Public functions

auto executor() -> Executor&
obtains the running executor
void schedule(Task task)
schedules an active task immediately to the worker's queue
template<typename T>
void run_and_wait(T&& target)
runs the given target and waits until it completes

Function documentation

Executor& tf::Runtime::executor()

obtains the running 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();

void tf::Runtime::schedule(Task task)

schedules an active task immediately to the worker's queue

Parameters
task the given active task to schedule immediately

This member function immediately schedules an active task to the task queue of the associated worker in the 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. Consider the following example:

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

The executor will first run the condition task A which returns 0 to inform the scheduler to go to the runtime task B. During the execution of B, it directly schedules task C without going through the normal taskflow graph scheduling process. At this moment, task C is active because its parent taskflow is running. When the taskflow finishes, we will see both B and C in the output.

template<typename T>
void tf::Runtime::run_and_wait(T&& target)

runs the given target and waits until it completes

A target can be (1) a callable to spawn a subflow or (2) a composable target with tf::Graph& T::graph() defined

// complete a subflow synchronously
taskflow.emplace([](tf::Runtime& rt){
  rt.run_and_wait([](tf::Runtime& sf){
    tf::Task A = sf.emplace([](){});
    tf::Task B = sf.emplace([](){});
  }); 
});

// complete a custom graph synchronously
tf::Taskflow taskflow;
taskflow.emplace([](){});
taskflow.emplace([&](tf::Runtime& rt){
  rt.run_and_wait(taskflow);
});