The Padre Task Manager is responsible for scheduling,
queueing and executing all operations that do not occur in the main application thead.

While there is rarely any need for code elsewhere in Padre or a plugin to make calls to this API,
documentation is included for maintenance purposes.

It spawns and manages a pool of workers which act as containers for the execution of standalone serialisable tasks.
This execution model is based loosely on the CPAN Process API,
and involves the parent process creating Padre::Task objects representing the work to do.
These tasks are serialised to a bytestream,
passed down a shared queue to an appropriate worker,
deserialised back into an object,
executed,
and then reserialised for transmission back to the parent thread.

Tasks operate on a shared-nothing basis.
Each worker is required to reload any modules needed by the task,
and the task cannot access any of the data structures.
To compensate for these limits,
tasks are able to send messages back and forth between the instance of the task object in the parent and the instance of the same task in the child.

Using this messaging channel,
a task object in the child can send status message or incremental results up to the parent,
and the task object in the parent can make changes to the GUI based on these messages.

The same messaging channel allows a background task to be cancelled elegantly by the parent,
although support for the "cancel" message is voluntary on the part of the background task.

Services are implemented via the Padre::Service API.
This is nearly identical to,
and sub-classes directly,
the Padre::Task API.

The main difference between a task and a service is that a service will be allocated a private,
unused and dedicated worker that has never been used by a task.
Further,
workers allocated to services will also not be counted against the "maximum workers" limit.

The new constructor creates a new Task Manager instance. While it is theoretically possible to create more than one instance, in practice this is never likely to occur.

The constructor has a single compulsory parameter, which is an object that implements the "message conduit" role Padre::Wx::Role::Conduit.

The message conduit is an object which provides direct integration with the underlying child-to-parent messaging pipeline, which in Padre is done via Wx::PlThreadEvent thread events.

Because the message conduit is provided to the constructor, the Task Manager itself is able to function with no Wx-specific code whatsoever. This simplifies implementation, allows sophisticated test rigs to be created, and makes it easier for us to spin off the Task Manager as a some notional standalone CPAN module.

The active accessor returns true if the task manager is currently running, or false if not. Generally task manager startup will occur relatively early in the Padre startup sequence, and task manager shutdown will occur relatively early in the shutdown sequence (to prevent accidental task execution during shutdown).

The maximum accessor returns the maximum quantity of worker threads that the task manager will use for running ordinary finite-length tasks. Once the number of active workers reaches the maximum limit, futher tasks will be pushed onto a queue to wait for a free worker.

The cancelled method is used with the "task ownership" feature of the Padre::Task 3.0 API to signal tasks running in the background that were created by a particular object that they should voluntarily abort as their results are no longer wanted.

The best_worker method is used to find the best worker from the worker pool for the execution of a particular task object.

This method makes use of a number of different strategies for optimising the way in which workers are used, such as maximising worker reuse for the same type of task, and "specialising" workers for particular types of tasks.

If all existing workers are in use this method may also spawn new workers, up to the maximum worker limit. Without the slave master logic enabled this will result in the editor blocking in the foreground briefly, this is something we can live with until the slave master feature is working again.

Returns a Padre::TaskWorker object, or undef if there is no worker in which the task can be run.