SBCL supports a system-wide event scheduler implemented on top of
setitimer
that also works with threads but does not require a
separate scheduler thread.
The following example schedules a timer that writes “Hello, word” after two seconds.
(schedule-timer (make-timer (lambda () (write-line "Hello, world") (force-output))) 2)
It should be noted that writing timer functions requires special care, as the dynamic environment in which they run is unpredictable: dynamic variable bindings, locks held, etc, all depend on whatever code was running when the timer fired. The following example should serve as a cautionary tale:
(defvar *foo* nil) (defun show-foo () (format t "~&foo=~S~%" *foo*) (force-output t)) (defun demo () (schedule-timer (make-timer #'show-foo) 0.5) (schedule-timer (make-timer #'show-foo) 1.5) (let ((*foo* t)) (sleep 1.0)) (let ((*foo* :surprise!)) (sleep 2.0)))
Class precedence list:
timer, structure-object, t
Timer type. Do not rely on timers being structs as it may change in future versions.
Create a timer object that's when scheduled runs
function
. Ifthread
is a thread then that thread is to be interrupted withfunction
. Ifthread
ist
then a new thread is created each timerfunction
is run. Ifthread
isnil
thenfunction
can be run in any thread. Whenthread
is nott
,interrupt-thread
is used to runfunction
and the ordering guarantees ofinterrupt-thread
also apply here.function
always runs with interrupts disabled butwith-interrupts
is allowed.
See if
timer
will still need to be triggered afterdelta
seconds from now. For timers with a repeat interval it returns true.
Schedule
timer
to be triggered attime
. Ifabsolute-p
thentime
is universal time, but non-integral values are also allowed, elsetime
is measured as the number of seconds from the current time. Ifrepeat-interval
is given,timer
is automatically rescheduled upon expiry.