The TaskRunner

The task runner runs long-running operations on a puzzle. It is used to run operations that take more than a frame to complete, and uses a thread to do so. Currently, there are four tasks that use it: The Word Solver, the Anagram Solver, the Theme Word Fitter, and the Grid Fill Task.

API and State

All tasks must inherit from PuzzleTask, and implement the run and set_run_info class methods.

  • task_runner_run(): Transitions to RUNNING. Initializes a new TaskContext. If a previous COMPLETE task existed, it is reset first.

  • task_runner_cancel(): Cancels the task. The task enters the COMPLETE state upon yielding. Results collected up to the cancellation point remain accessible via task_runner_get_result().

  • task_runner_reset(): Immediately transitions the runner to READY. If a thread is active, it is cancelled and marked for background cleanup; its results become inaccessible immediately.

Progress Updates

Tasks can provide intermediate results while they are running. There are two ways of doing this that are thread safe:

  1. There’s a count gint that can be used to indicate number of runs. It can be updated with g_atomic_int_inc ()

  2. There’s a results array (with associated GMutex) that results (a gpointer) can be placed in. Either unique results can be put there, or a single item that’s updated. In the case of the latter, care should be taken to lock it.

In the main thread, the UI can poll the task for updates in a timeout. In addition, there’s a thread-safe TaskRunner::updated signal that can be triggered within the job by calling puzzle_task_update(). This can let the main thread know to check the results array for updates.

When the task is done TaskRunner::finished is emitted.