]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/timer.el
authors.el trivia
[gnu-emacs] / lisp / emacs-lisp / timer.el
index 0e007ff71760f364fa9ccc83d9384ed8cce57667..b6b7c266263e115736aad397868159f389f209c0 100644 (file)
@@ -1,6 +1,6 @@
 ;;; 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
@@ -402,10 +402,6 @@ This function returns a timer object which you can use in `cancel-timer'."
     (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.")
 
@@ -417,24 +413,27 @@ event (such as keyboard input, input from subprocesses, or a certain time);
 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.