Tomographer  v5.4
Tomographer C++ Framework Documentation
TaskDispatcher Interface

The task dispatcher takes care of running tasks. It should handle tasks provided by a Task Interface compliant template parameter, should allow these tasks to share data via a TaskCData Interface compliant type also specified as template parameter.

Since
Changed in Tomographer 5.0: Removed the results collector entirely. Now the tasks must be Resultable 's which the task dispatcher simply collects and make available to the caller with collectedTaskResults().

What the task dispatcher should do

The task dispatcher is responsible for scheduling and running the tasks. See Tomographer::MultiProc::Sequential::TaskDispatcher for a simple example.

It should be provided, or should otherwise have knowledge of:

  • A task type (TaskType), which obeys the Task Interface ;
  • A constant shared data structure (which we later refer to as TaskCData), which obeys the TaskCData Interface and which provides the necessary input data to carry out the tasks ;

Upon execution, say within a run() method exposed by the task dispatcher, the task dispatcher is expected to do the following steps, in this order:

  • Schedule the tasks however they are meant to be run (in different threads, in different processes, serially one at a time, etc.), and run each task following these steps:
    • Get the input to the new task from the TaskCData, by invoking its getTaskInput() method;
    • Instantiate a new TaskType instance, providing it the input, as well as a suitable logger instance so that the task can log messages;
    • Run the task, by calling its run() function. You must provide a pointer to an object obeying the TaskManagerIface Interface, which allows the task to query whether status updates were requested. This object may be for instance a relevant private class or struct, it does not need to be public type. Theoretically, it could also be the task dispatcher itself (if it exposes the relevant methods), but this would mean having to publicly expose functions which should really only be called by the tasks. See Tomographer::MultiProc::Sequential::TaskDispatcher for an example.
    • Recover the task's result using its stealResult() or getResult() method.
  • All the time during the above task execution, if the a status report is requested explicitly from an external caller (e.g. a signal handler) with a call to this class' requestStatusReport(), then the TaskManagerIface provided to the task's run() function should inform the task to provide its status report (see Task Interface).

    When a status report is requested, the tasks will submit their reports to the TaskManagerIface (see Task Interface). Once all the reports are received, they should be combined into a full status report (Tomographer::MultiProc::FullStatusReport), and the status report handler (set by setStatusReportHandler()) should be called.

    The same holds if a status report is periodically due because a periodic status report was enabled (e.g. with requestPeriodicStatusReport() called before tasks were started). In this case it is the TaskManagerIface which should tell the task to submit a status report every so many milliseconds using the same interface.

  • After all tasks have completed, call the results collectors' runsFinished() method to finalize the results.
Note
The tasks, the results collector and the constant data structure do NOT know in which kind of multiprocessing environment they will be run (they just express some abstract task to be carried out). Any data protection, data race conditions, approprate thread locking, communication of results across processes, or whatever other housekeeping is required is the task dispatcher's responsibility; not that of the tasks. See Tomographer::MultiProc::OMP::TaskDispatcher for an example; there, sections where data could be accessed simultaneously by different threads are protected by #pragma omp critical blocks.

The API exposed by the task dispatcher

The exact APIs of how these tasks are specified, managed and run is not clearly specified, but it is strongly advised to follow a model such as the simplistic Tomographer::MultiProc::Sequential::TaskDispatcher or the OpenMP-based Tomographer::MultiProc::OMP::TaskDispatcher.

The TaskDispatcher must however provide the following methods:

void setStatusReportHandler(Fn fn)
The argument should be a callable (e.g. lambda function) which accepts a single paramter of const reference to a FullStatusReportType.
void requestStatusReport()
Initiate a status report query. The call will typically return immediately, and sometime later the callback set by setStatusReportHandler() will be called with the relevant status report information.

This function should be safe to be called from a signal handler. This requirement severly limits what this function can do – the best usually is simply to set a value to a volatile std::sig_atomic_int flag (or another std::atomic type). See http://en.cppreference.com/w/cpp/utility/program/signal#Signal_handler and http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03

void requestPeriodicStatusReport(int milliseconds)
Request that the task manager periodically send a status report to the handler set by setStatusReportHandler(). The interval time is specified in milliseconds. Pass the value -1 to disable periodic status reports.
void requestInterrupt()
Interrupt all tasks as soon as possible.

This function should be safe to be called from a signal handler. This requirement severly limits what this function can do – the best usually is simply to set a value to a volatile std::sig_atomic_int flag (or another std::atomic type). See http://en.cppreference.com/w/cpp/utility/program/signal#Signal_handler and http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03

The TaskDispatcher must also provide the following typedefs:

typedef ... TaskType;
The Task Interface -compliant type used to describe a task.
typedef .. FullStatusReportType;
A specialized type (or subclass) of Tomographer::MultiProc::FullStatusReport which is passed as parameter to the callback function given to setStatusReportHandler()