simple tasks
1.3.0A very simple task scheduling framework.
Table of Contents
About simple-tasks
Recently I noticed that I seem to write a similar pattern way too often: Some form of scheduling or task management part. Usually this is due to the need of executing some task in a specific thread, or simply wanting to schedule something for processing in the background.
Basic Usage
Load it through ASDF or Quicklisp:
(ql:quickload :simple-tasks)
Before we can do anything, we need to have a manager to run tasks with. These are called runner
s. Usually you will want a queued-runner
which will use threading capabilities if the system provides them, and thus can process tasks in the background.
(defvar *runner* (make-instance 'simple-tasks:queued-runner))
Next we'll want to start the runner, if possible in a separate thread. The standard start-runner
function does not do this, as you might want to set up the thread scenario yourself, or perhaps even inject the runner into a different thread. However, for the common scenario, there's make-runner-thread
.
(defvar *thread* (simple-tasks:make-runner-thread *runner*))
Now we can finally create task
s and send them off for processing! Out of the box, simple-tasks provides three classes to do remote evaluation with: call-task
, blocking-call-task
, and callback-task
. However, adding your own is very easy. Just subclass task
and implement run-task
.
(defvar *task* (make-instance 'simple-tasks:call-task :func (lambda () (print "hi"))))
Finally we need to send off the task for processing.
(simple-tasks:schedule-task *task* *runner*)
All call-task
s also save the return-values
of the function they're calling, so you can read that out later. Usually if you want to do so, you'll want to either block until the task is done, or delegate to a callback function. The former is made convenient through with-body-as-task
.
(simple-tasks:with-body-as-task (*runner*)
(sleep 1)
(expt 2 12))
In the case that a task encounters a failure during a run, it sets its status to :errored
and saves the current environment. You can inspect this environment at any later point by fetching it with error-environment
and looking at its contents with the various functions Dissect provides. This is mostly useful in a scenario where you cannot use a debugger and thus just automatically invoke the skip
restart in the runner thread. With the environment saved, the error can still be inspected elsewhere or at a later date.
(dissect:present
(simple-tasks:error-environment
(simple-tasks:schedule-task
(make-instance 'simple-tasks:blocking-call-task :func (lambda () (error "Hi"))) *runner*)))
And that's pretty much it.
(simple-tasks:stop-runner *runner*)
Extending simple-tasks
If you want to add flexibility by creating your own specialised task classes, you should look at task
, run-task
, and schedule-task
. Usually you can get away by just subclassing task
, and adding a run-task
method to do your calculations in. If you also need to modify the behaviour of the scheduling, adding :after
methods to schedule-task
can also be useful.
In case that the existing runners aren't suited to your needs, adding one should also not be much of a problem. Simply subclass runner
, and implement appropriate methods for start-runner
, stop-runner
, and schedule-task
. The existing methods on runner
will take care of keeping the status
in sync and making sure no invalid calls can be made.
Also See
- Dissect for error environment capture and inspection.
System Information
Definition Index
-
SIMPLE-TASKS
- ORG.SHIRAKUMO.SIMPLE-TASKS
No documentation provided.-
EXTERNAL SPECIAL-VARIABLE *RUNNER*
Bound to the current runner if within a runner context. Otherwise, set to NIL. Useful to detect if a task is run in a particular runner to avoid conflicts.
-
EXTERNAL SPECIAL-VARIABLE +NO-THREADING-STUMP+
Constant to hold an instance of NO-THREADING-STUMP.
-
EXTERNAL SPECIAL-VARIABLE +STATUS-ENDED+
Constant matching any ended (not necessarily successful) status. :STOPPING Object is in the process of being stopped. :STOPPED Object has been stopped. :COMPLETED Object successfully completed execution. :ERRORED Object ended execution with an error.
-
EXTERNAL SPECIAL-VARIABLE +STATUS-RUNNING+
Constant matching a running status. :RUNNING Object is currently executing.
-
EXTERNAL SPECIAL-VARIABLE +STATUS-STARTED+
Constant matching any started (not necessarily running) status. :CREATED Object has been initialized, but not started. :SCHEDULED Object has been scheduled for execution. :RUNNING Object is currently executing.
-
EXTERNAL CLASS BLOCKING-CALL-TASK
Task class to perform a function call once run. Blocks the scheduling thread until it is done. See CALL-TASK See BLOCKING-TASK
-
EXTERNAL CLASS BLOCKING-TASK
A task that will block after being scheduled until it is done or interrupted. When SCHEDULE-TASK is called on this, it establishes two restarts: ABORT to forcibly abort (interrupt) the task. UNBLOCK to resume execution in the current thread and leave the task running. If a restart or similar exit functionality is invoked that leaves the scope of SCHEDULE-TASK, the task is interrupted. Note that the restarts are not useful on systems without thread support. In such a case the task will be interrupted either way, due to the very nature of running in the current thread. See AWAIT See INTERRUPT-TASK See NOTIFYING-TASK
-
EXTERNAL CLASS CALL-TASK
Task class to perform a function call once run. Stores the return values.
-
EXTERNAL CLASS CALLBACK-TASK
Task class to perform a function call once run and call a callback upon completion. If the task completes successfully, the callback function is called with each return value as an argument. Note that the callback function is called within the runner environment which may be different from the scheduler environment. See CALL-TASK
-
EXTERNAL CLASS NO-THREADING-STUMP
Stump class to stand in place of a value on systems without threading support.
-
EXTERNAL CLASS NOTIFYING-TASK
A task that will notify a condition upon completion. This is particularly useful in conjunction with AWAIT.
-
EXTERNAL CLASS QUEUED-RUNNER
Queued runner. Runs tasks in a thread if threading is available. Noe that START-RUNNER for this runner will block the current thread.
-
EXTERNAL CLASS RUNNER
Basic runner. Runs task as soon as scheduled.
-
EXTERNAL CLASS STATUS-OBJECT
A class that has a status.
-
EXTERNAL CLASS TASK
Basic task class.
-
EXTERNAL CONDITION RUNNER-CONDITION
Condition superclass for conditions related to runner operations.
-
EXTERNAL CONDITION RUNNER-NOT-STARTED
Condition signalled when the runner is not yet started, but has to be.
-
EXTERNAL CONDITION RUNNER-NOT-STOPPED
Condition signalled when the runner did not stop properly.
-
EXTERNAL CONDITION TASK-ALREADY-SCHEDULED
Condition signalled when attempting to reschedule an already scheduled task.
-
EXTERNAL CONDITION TASK-CONDITION
Condition superclass for task operation related conditions.
-
EXTERNAL CONDITION TASK-ERRORED
Condition signalled when a task failed to run properly.
-
EXTERNAL TYPE-DEFINITION STATUS
A status can be a SYMBOL, a STATUS-OBJECT, or a LIST composed of SYMBOLs.
-
EXTERNAL FUNCTION ABORT
- &OPTIONAL
- CONDITION
- &REST
Transfer control to a restart named ABORT, signalling a CONTROL-ERROR if none exists.
-
EXTERNAL FUNCTION CALL-AS-TASK
- FUNCTION
- RUNNER
- &OPTIONAL
- TASK-CLASS
- &REST
Call function within a task, usually a BLOCKING-CALL-TASK. Depending on the task's STATUS after SCHEDULE-TASK returns, the following happens. :COMPLETED The task's return values are returned. :ERRORED A condition of type TASK-ERRORED is signalled. T The task is returned. See SCHEDULE-TASK See BLOCKING-CALL-TASK
-
EXTERNAL FUNCTION MAKE-RUNNER-THREAD
- RUNNER
- &REST
Make a thread to call START-RUNNER on RUNNER in. On platforms with thread support, this returns the new thread. On platforms without, this simply calls START-RUNNER and returns NIL. See START-RUNNER
-
EXTERNAL GENERIC-FUNCTION AWAIT
- TASK
- STATUS
- &REST
Wait for the TASK to match a certain STATUS. On systems without thread support this does nothing. See STATUS=
-
EXTERNAL GENERIC-FUNCTION BACK-QUEUE
- RUNNER
- &REST
The current back-queue of the runner. Used to swap with QUEUE when events are handled. See QUEUE
-
EXTERNAL GENERIC-FUNCTION CALLBACK
- CALLBACK-TASK
- &REST
The function to call upon completion of the task. See CALLBACK-TASK
-
EXTERNAL GENERIC-FUNCTION (SETF CALLBACK)
- NEW-VALUE
- OBJECT
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION CVAR
- OBJECT
- &REST
The condition variable used to exchange signals. See QUEUED-RUNNER See BLOCKING-CALL-TASK
-
EXTERNAL GENERIC-FUNCTION (SETF CVAR)
- NEW-VALUE
- OBJECT
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION ERROR-ENVIRONMENT
- TASK
- &REST
An environment object that is stored in case the task fails to run properly. See DISSECT:ENVIRONMENT
-
EXTERNAL GENERIC-FUNCTION (SETF ERROR-ENVIRONMENT)
- NEW-VALUE
- OBJECT
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION FUNC
- CALL-TASK
- &REST
The function the call-task calls once it is run. See CALL-TASK
-
EXTERNAL GENERIC-FUNCTION (SETF FUNC)
- NEW-VALUE
- OBJECT
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION INTERRUPT-TASK
- TASK
- RUNNER
- &REST
Interrupt the TASK to stop it from execution on RUNNER. If the task is currently on the RUNNER's queue to be executed (:SCHEDULED), it is removed from the queue. If the task is currently running, it is forcibly aborted. In either case, the task's status is changed to :STOPPED and it will not execute further. On systems without thread support this does nothing. If this is called with the RUNNER being T, the current runner of the TASK is used, if possible. If this is called with the RUNNER being NIL, the actual termination mechanism for the task is performed, leading it to be terminated.
-
EXTERNAL GENERIC-FUNCTION LOCK
- OBJECT
- &REST
The lock used to coordinate task scheduling with the runner. See QUEUED-RUNNER
-
EXTERNAL GENERIC-FUNCTION (SETF LOCK)
- NEW-VALUE
- OBJECT
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION QUEUE
- RUNNER
- &REST
The current task queue of the runner. Do not directly push tasks to this! Use SCHEDULE-TASK instead. This queue is also NOT indicative of which tasks have yet to be run, or which ones have. When the queued runner runs, it retains the current queue for processing and sets a new, empty queue on the runner. As such, when you look at the queue at any particular moment, tasks that are not in it might not have run yet.
-
EXTERNAL GENERIC-FUNCTION RETURN-VALUES
- CALL-TASK
- &REST
Returns the values that the call returned. See CALL-TASK
-
EXTERNAL GENERIC-FUNCTION (SETF RETURN-VALUES)
- NEW-VALUE
- OBJECT
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION RUN-TASK
- TASK
- &REST
Run the given task object directly. One restart is established: STOP to forcibly stop (interrupt) the task. Assigns the :STOPPED status.
-
EXTERNAL GENERIC-FUNCTION RUNNER
- TASK
- &REST
The runner the task is scheduled on. See TASK
-
EXTERNAL GENERIC-FUNCTION (SETF RUNNER)
- NEW-VALUE
- CONDITION
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION SCHEDULE-TASK
- TASK
- RUNNER
- &REST
Schedule the task object for running. The task may or may not be run immediately, depending on the runner and given system support. Tasks are guaranteed to be run in the same order as they are scheduled. See RUN-TASK
-
EXTERNAL GENERIC-FUNCTION START-RUNNER
- RUNNER
- &REST
Start the the runner.
-
EXTERNAL GENERIC-FUNCTION STATUS
- STATUS-OBJECT
- &REST
Current status indicator of the status-object.
-
EXTERNAL GENERIC-FUNCTION (SETF STATUS)
- NEW-VALUE
- OBJECT
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION STATUS=
- A
- B
- &REST
Compare two statuses with each other (commutative).
-
EXTERNAL GENERIC-FUNCTION STOP-RUNNER
- RUNNER
- &REST
Stop the the runner.
-
EXTERNAL GENERIC-FUNCTION TASK
- TASK-CONDITION
- &REST
The task related to the condition.
-
EXTERNAL GENERIC-FUNCTION (SETF TASK)
- NEW-VALUE
- CONDITION
- &REST
No documentation provided. -
EXTERNAL GENERIC-FUNCTION TASK-READY-P
- TASK
- &REST
Returns T if the task is ready to be run.
-
EXTERNAL GENERIC-FUNCTION THREAD
- OBJECT
- &REST
Returns the current thread associated with the queued-runner if any. See QUEUED-RUNNER
-
EXTERNAL MACRO WITH-BODY-AS-TASK
- RUNNER
- &OPTIONAL
- TASK-CLASS
- &REST
- &BODY
- BODY
- &REST
Evaluate BODY within a task, usually a BLOCKING-CALL-TASK. See CALL-AS-TASK