;;; timer.el --- run a function with args at some time in future
-;; Copyright (C) 1996, 2001-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2012 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Package: emacs
"Third-to-last timer that was run.")
(defvar timer-max-repeats 10
- "*Maximum number of times to repeat a timer, if many repeats are delayed.
+ "Maximum number of times to repeat a timer, if many repeats are delayed.
Timer invocations can be delayed because Emacs is suspended or busy,
or because the system's time changes. If such an occurrence makes it
appear that many invocations are overdue, this variable controls
(timer-activate-when-idle timer t)
timer))
\f
-(defun with-timeout-handler (tag)
- "This is the timer function used for the timer made by `with-timeout'."
- (throw tag 'timeout))
-
(defvar with-timeout-timers nil
"List of all timers used by currently pending `with-timeout' calls.")
if the program loops without waiting in any way, the timeout will not
be detected.
\n(fn (SECONDS TIMEOUT-FORMS...) BODY)"
- (declare (indent 1))
+ (declare (indent 1) (debug ((form body) body)))
(let ((seconds (car list))
- (timeout-forms (cdr list)))
- `(let ((with-timeout-tag (cons nil nil))
- with-timeout-value with-timeout-timer
- (with-timeout-timers with-timeout-timers))
- (if (catch with-timeout-tag
- (progn
- (setq with-timeout-timer
- (run-with-timer ,seconds nil
- 'with-timeout-handler
- with-timeout-tag))
- (push with-timeout-timer with-timeout-timers)
- (setq with-timeout-value (progn . ,body))
- nil))
- (progn . ,timeout-forms)
- (cancel-timer with-timeout-timer)
- with-timeout-value))))
+ (timeout-forms (cdr list))
+ (timeout (make-symbol "timeout")))
+ `(let ((-with-timeout-value-
+ (catch ',timeout
+ (let* ((-with-timeout-timer-
+ (run-with-timer ,seconds nil
+ (lambda () (throw ',timeout ',timeout))))
+ (with-timeout-timers
+ (cons -with-timeout-timer- with-timeout-timers)))
+ (unwind-protect
+ ,@body
+ (cancel-timer -with-timeout-timer-))))))
+ ;; It is tempting to avoid the `if' altogether and instead run
+ ;; timeout-forms in the timer, just before throwing `timeout'.
+ ;; But that would mean that timeout-forms are run in the deeper
+ ;; dynamic context of the timer, with inhibit-quit set etc...
+ (if (eq -with-timeout-value- ',timeout)
+ (progn ,@timeout-forms)
+ -with-timeout-value-))))
(defun with-timeout-suspend ()
"Stop the clock for `with-timeout'. Used by debuggers.