X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Flate-extensions.lisp;h=d18939be21377e8f46c8ae003b33eb846fc40d82;hb=8a33054f6541596c61b091e2b77118deda1511e2;hp=59a2fd6770702677c7310823c94d1caa2fdc60fd;hpb=11802a47e04b0dbfbfec03d8b438fb59f84ce35d;p=sbcl.git diff --git a/src/code/late-extensions.lisp b/src/code/late-extensions.lisp index 59a2fd6..d18939b 100644 --- a/src/code/late-extensions.lisp +++ b/src/code/late-extensions.lisp @@ -331,6 +331,7 @@ See also the declarations SB-EXT:GLOBAL and SB-EXT:ALWAYS-BOUND." (go :restart))))))) (defmacro wait-for (test-form &key timeout) + #!+sb-doc "Wait until TEST-FORM evaluates to true, then return its primary value. If TIMEOUT is provided, waits at most approximately TIMEOUT seconds before returning NIL. @@ -342,3 +343,25 @@ deadline. Experimental: subject to change without prior notice." `(dx-flet ((wait-for-test () (progn ,test-form))) (%wait-for #'wait-for-test ,timeout))) + +(defmacro with-progressive-timeout ((name &key seconds) + &body body) + #!+sb-doc + "Binds NAME as a local function for BODY. Each time #'NAME is called, it +returns SECONDS minus the time that has elapsed since BODY was entered, or +zero if more time than SECONDS has elapsed. If SECONDS is NIL, #'NAME +returns NIL each time." + (with-unique-names (deadline time-left sec) + `(let* ((,sec ,seconds) + (,deadline + (when ,sec + (+ (get-internal-real-time) + (round (* ,seconds internal-time-units-per-second)))))) + (flet ((,name () + (when ,deadline + (let ((,time-left (- ,deadline (get-internal-real-time)))) + (if (plusp ,time-left) + (* (coerce ,time-left 'single-float) + ,(/ 1.0 internal-time-units-per-second)) + 0))))) + ,@body))))