Class chained_task

Class Documentation

class concore::v1::chained_task

A type of tasks that can be chained with other such tasks to create graphs of tasks.

This is a wrapper on top of a task, and cannot be directly interchanged with a task. This can directly enqueue the encapsulated task, and also, one can create a task on top of this one (as this defines the call operator, and it’s also a functor).

One can create multiple chained_task objects, then call add_dependency() oradd_dependencies() to create dependencies between such task objects. Thus, one can create graphs of tasks from chained_task objects.

The built graph must be acyclic. Cyclic graphs can lead to execution stalls.

After building the graph, the user should manually start the execution of the graph by enqueueing a chained_task that has no predecessors. After completion, this will try to enqueue follow-up tasks, and so on, until all the graph is completely executed.

A chained task will be executed only after all the predecessors have been executed. If a task has three predecessors it will be executed only when the last predecessor completes. Looking from the opposite direction, at the end of the task, the successors are checked; the number of active predecessors is decremented, and, if one drops to zero, that successor will be enqueued.

The chained_task can be configured with an executor this will be used when enqueueing successor tasks.

If a task throws an exception, the handler in the associated task_group is called (if set) and the execution of the graph will continue. Similarly, if a task from the graph is canceled, the execution of the graph will continue as if the task wasn’t supposed to do anything.

See

task, add_dependency(), add_dependencies(), task_group

Public Functions

chained_task() = default

Default constructor. Constructs an invalid chained_task. Such a task cannot be placed in a graph of tasks.

chained_task(task t, any_executor executor = {})

Constructor.

This will initialize a valid

chained_task. After this constructor, add_dependency() and add_dependencies() can be called to add predecessors and successors of this task.
Parameters
  • t: The task to be executed

  • executor: The executor to be used for the successor tasks (optional)

If this tasks tries to start executing successor tasks it will use the given executor.

If no executor is given, the spawn_executor will be used.

See

add_dependency(), add_dependencies(), task

template<typename F>
chained_task(F f, any_executor executor = {})

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

void operator()()

The call operator.

This will be called when executing the chained_task. It will execute the task received on constructor and then will check if it needs to start executing successors it will try to start executing the successors that don’t have any other active predecessors.

This will use the executor given at construction to start successor tasks.

void set_exception_handler(except_fun_t except_fun)

Sets the exception handler for enqueueing tasks.

The exception handler set here will be called whenever an exception is thrown while enqueueing a follow-up task. It will not be called whenever the task itself throws an exception; that will be handled by the exception handler set in the group of the task.

Parameters
  • except_fun: The function to be called whenever an exception occurs.

See

task_group::set_exception_handler

operator bool() const noexcept

Bool conversion operator.

Indicates if this is a valid chained task.

void clear_next()

Clear all the dependencies that go from this task.

This is useful for constructing and destroying task graphs manually.