anchor.diff:      (apropos-time-handler (time-handler identifier)))
     (:method ((handler time-handler))
       (let ((*print-pretty* NIL))
  -      (format NIL "[Time Handler] ~s with ~d active timers.~%~
  +      (format NIL "[Time Handler] ~s with ~d active timers expecting ~a.~%~
                    ~:[No docstring available.~;Docstring: ~:*~a~]"
  -              (identifier handler) (length (active-timers handler)) (docstring handler)))))
  +              (identifier handler) (length (active-timers handler)) (arguments handler) (docstring handler)))))
   
   (defvar *unix-epoch-difference*
     (encode-universal-time 0 0 0 1 1 1970 0))
  
positive.code:               do (destroy-thread thread)))
        (remhash identifier *timer-map*))))
  
  (defun set-timer-function (identifier launcher-function handler-function &key docstring)
    ""
    (assert (symbolp identifier) () "IDENTIFIER has to be a symbol.")
    (when (time-handler identifier)
      (v:debug :timer "Redefining handler ~a" identifier)
      (when (active-timers (time-handler identifier))
        (v:warn :timer "Redefining running timer ~a" identifier)))
    (setf (time-handler identifier)
          (make-instance 'time-handler
                         :identifier identifier :launcher-function launcher-function
                         :handler-function handler-function :docstring docstring)))
  
  (defgeneric apropos-time-handler (handler)
    (:documentation "")
  
negative.code:          (if universal
               universal
               (+ unix *unix-epoch-difference*)))
          ((or in)
           (+ (get-universal-time)
              (parse-delay in)))
          ((and from every)
           (list (parse-delay from)
                 (parse-delay every)
                 (if until (parse-delay until) -1)))))))
  
  (defun timer-timeout (type delay function)
    (flet ((inner (time-target)
             (v:trace :timer "Timing ~a seconds" (- time-target (get-universal-time)))
             (loop while (< (get-universal-time) time-target)
                   do (sleep (- time-target (get-universal-time))))
             (handler-bind
                 ((error #'(lambda (err)
                             (v:warn :timer "ERROR: ~a" err)
                             (when *debugger*
                               (invoke-debugger err)))))
               (funcall function))))
      (ecase type
        ((:date :time :once :when)
         (inner (if (consp delay) (car delay) delay)))
        ((:interval :repeating :loop :every)
         (if (listp delay)
             (destructuring-bind (from every until) delay
               (loop for current = from
                       then (+ (get-universal-time) every)
                     while (or (< until 0)
                               (< (get-universal-time) until))
                     do (inner current)
                        (thread-yield)))
             (loop do (inner (+ (get-universal-time) delay))
                      (thread-yield)))))))
  
  (defun launch-timer (handler type delay arguments)
    (let ((thread) (launch-done NIL))
      (setf thread (make-thread #'(lambda ()
                                    (unwind-protect
                                         (timer-timeout
                                          type delay
                                          #'(lambda () (apply (handler-function handler) arguments)))
                                      ;; Yield until the launch has completed.
                                      (loop do (thread-yield) until launch-done)
                                      (with-lock-held ((handler-lock handler))
                                        (v:debug :timer "CLEANUP ~a" thread)
                                        (setf (active-timers handler)
                                              (delete thread (active-timers handler))))))
                                :name (format NIL "Timer thread for ~a" handler)))
      (with-lock-held ((handler-lock handler))
        (push thread (active-timers handler)))
      ;; We can only set this now to ensure the thread definitely waits
  