extend `sync/timeout' to allow a tail-position fail thunk for polling

This commit is contained in:
Matthew Flatt 2010-12-10 14:17:08 -07:00
parent 7d8e4f81f2
commit 2b4f1a6908
4 changed files with 42 additions and 27 deletions

View File

@ -399,20 +399,22 @@
[(and (eq? evt 'wait)
(not handler?))
#t]
;; `yield' is supposed to return immediately if the
;; event is already ready:
[(and (evt? evt) (sync/timeout 0 (wrap-evt evt (lambda (v) (list v)))))
=> (lambda (v) (car v))]
[handler?
(sync (if (eq? evt 'wait)
(wrap-evt e (lambda (_) #t))
evt)
(handle-evt ((eventspace-queue-proc e))
(lambda (v)
(when v (handle-event v))
(yield evt))))]
[else
(sync evt)]))]))
(define (wait-now)
(if handler?
(sync (if (eq? evt 'wait)
(wrap-evt e (lambda (_) #t))
evt)
(handle-evt ((eventspace-queue-proc e))
(lambda (v)
(when v (handle-event v))
(yield evt))))
(sync evt)))
(if (evt? evt)
;; `yield' is supposed to return immediately if the
;; event is already ready:
(sync/timeout wait-now evt)
(wait-now))]))]))
(define yield-refresh
(lambda ()

View File

@ -207,17 +207,20 @@ pseudo-randomly for the result; the
random-number generator that controls this choice.}
@defproc[(sync/timeout [timeout-secs (or/c nonnegative-number? #f)]
@defproc[(sync/timeout [timeout (or/c #f (and/c real? (not/c negative?)) (-> any))]
[evt evt?] ...+)
any]{
Like @racket[sync], but returns @racket[#f] if @racket[timeout-secs]
is not @racket[#f] and if @racket[timeout-secs] seconds pass without a
successful synchronization.
Like @racket[sync] if @racket[timeout] is @racket[#f]. If
@racket[timeout] is a real number, then the result is @racket[#f]
if @racket[timeout] seconds pass without a
successful synchronization. If @racket[timeout] is a procedure, then
it is called in tail position if polling the @racket[evt]s discovers
no ready events.
If @racket[timeout-secs] is @racket[0], each @racket[evt] is checked
at least once before returning @racket[#f], so a @racket[timeout-secs]
value of @racket[0] can be used for polling.
A zero value for @racket[timeout] is equivalent to @racket[(lambda ()
#f)]. In either case, each @racket[evt] is checked at least once
before returning @racket[#f] or calling @racket[timeout].
See also @racket[alarm-evt] for an alternative timeout mechanism.}
@ -231,12 +234,11 @@ either all @racket[evt]s remain unchosen or the @racket[exn:break]
exception is raised, but not both.}
@defproc[(sync/timeout/enable-break [timeout-secs (or/c nonnegative-number? #f)]
@defproc[(sync/timeout/enable-break [timeout (or/c #f (and/c real? (not/c negative?)) (-> any))]
[evt evt?] ...+)
any]{
Like @racket[sync/enable-break], but with a timeout in seconds (or
@racket[#f]), as for @racket[sync/timeout].}
Like @racket[sync/enable-break], but with a timeout as for @racket[sync/timeout].}
@defproc[(choice-evt [evt evt?] ...) evt?]{

View File

@ -15,6 +15,7 @@
[ch (make-channel)])
(test #f sync/timeout 0 s p)
(test #f sync/timeout 0 s p)
(test 'nope sync/timeout (lambda () 'nope) s p)
(semaphore-post s)
(test p sync/timeout 0 p)
(test p sync p)
@ -23,6 +24,7 @@
(thread (lambda () (sync (system-idle-evt)) (semaphore-post s)))
(test p sync p)
(test p sync p)
(test p sync/timeout (lambda () 'nope) p)
(test s sync s)
(test #f sync/timeout 0 p)
(thread (lambda () (sync/timeout 0 p) (channel-put ch 7)))

View File

@ -5993,6 +5993,8 @@ static Scheme_Object *do_sync(const char *name, int argc, Scheme_Object *argv[],
if (!SCHEME_FALSEP(argv[0])) {
if (SCHEME_REALP(argv[0]))
timeout = (float)scheme_real_to_double(argv[0]);
else if (scheme_check_proc_arity(NULL, 0, 0, argc, argv))
timeout = 0.0;
if (timeout < 0.0) {
scheme_wrong_type(name, "non-negative real number", 0, argc, argv);
@ -6151,10 +6153,17 @@ static Scheme_Object *do_sync(const char *name, int argc, Scheme_Object *argv[],
}
}
return o;
} else if (tailok)
return scheme_false;
else
return NULL;
} else {
if (with_timeout && SCHEME_PROCP(argv[0])) {
if (tailok)
return _scheme_tail_apply(argv[0], 0, NULL);
else
return _scheme_apply(argv[0], 0, NULL);
} else if (tailok)
return scheme_false;
else
return NULL;
}
}
static Scheme_Object *sch_sync(int argc, Scheme_Object *argv[])