extend `sync/timeout' to allow a tail-position fail thunk for polling
This commit is contained in:
parent
7d8e4f81f2
commit
2b4f1a6908
|
@ -399,20 +399,22 @@
|
||||||
[(and (eq? evt 'wait)
|
[(and (eq? evt 'wait)
|
||||||
(not handler?))
|
(not handler?))
|
||||||
#t]
|
#t]
|
||||||
;; `yield' is supposed to return immediately if the
|
[else
|
||||||
;; event is already ready:
|
(define (wait-now)
|
||||||
[(and (evt? evt) (sync/timeout 0 (wrap-evt evt (lambda (v) (list v)))))
|
(if handler?
|
||||||
=> (lambda (v) (car v))]
|
|
||||||
[handler?
|
|
||||||
(sync (if (eq? evt 'wait)
|
(sync (if (eq? evt 'wait)
|
||||||
(wrap-evt e (lambda (_) #t))
|
(wrap-evt e (lambda (_) #t))
|
||||||
evt)
|
evt)
|
||||||
(handle-evt ((eventspace-queue-proc e))
|
(handle-evt ((eventspace-queue-proc e))
|
||||||
(lambda (v)
|
(lambda (v)
|
||||||
(when v (handle-event v))
|
(when v (handle-event v))
|
||||||
(yield evt))))]
|
(yield evt))))
|
||||||
[else
|
(sync 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
|
(define yield-refresh
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
|
|
@ -207,17 +207,20 @@ pseudo-randomly for the result; the
|
||||||
random-number generator that controls this choice.}
|
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?] ...+)
|
[evt evt?] ...+)
|
||||||
any]{
|
any]{
|
||||||
|
|
||||||
Like @racket[sync], but returns @racket[#f] if @racket[timeout-secs]
|
Like @racket[sync] if @racket[timeout] is @racket[#f]. If
|
||||||
is not @racket[#f] and if @racket[timeout-secs] seconds pass without a
|
@racket[timeout] is a real number, then the result is @racket[#f]
|
||||||
successful synchronization.
|
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
|
A zero value for @racket[timeout] is equivalent to @racket[(lambda ()
|
||||||
at least once before returning @racket[#f], so a @racket[timeout-secs]
|
#f)]. In either case, each @racket[evt] is checked at least once
|
||||||
value of @racket[0] can be used for polling.
|
before returning @racket[#f] or calling @racket[timeout].
|
||||||
|
|
||||||
See also @racket[alarm-evt] for an alternative timeout mechanism.}
|
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.}
|
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?] ...+)
|
[evt evt?] ...+)
|
||||||
any]{
|
any]{
|
||||||
|
|
||||||
Like @racket[sync/enable-break], but with a timeout in seconds (or
|
Like @racket[sync/enable-break], but with a timeout as for @racket[sync/timeout].}
|
||||||
@racket[#f]), as for @racket[sync/timeout].}
|
|
||||||
|
|
||||||
|
|
||||||
@defproc[(choice-evt [evt evt?] ...) evt?]{
|
@defproc[(choice-evt [evt evt?] ...) evt?]{
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[ch (make-channel)])
|
[ch (make-channel)])
|
||||||
(test #f sync/timeout 0 s p)
|
(test #f sync/timeout 0 s p)
|
||||||
(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)
|
(semaphore-post s)
|
||||||
(test p sync/timeout 0 p)
|
(test p sync/timeout 0 p)
|
||||||
(test p sync p)
|
(test p sync p)
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
(thread (lambda () (sync (system-idle-evt)) (semaphore-post s)))
|
(thread (lambda () (sync (system-idle-evt)) (semaphore-post s)))
|
||||||
(test p sync p)
|
(test p sync p)
|
||||||
(test p sync p)
|
(test p sync p)
|
||||||
|
(test p sync/timeout (lambda () 'nope) p)
|
||||||
(test s sync s)
|
(test s sync s)
|
||||||
(test #f sync/timeout 0 p)
|
(test #f sync/timeout 0 p)
|
||||||
(thread (lambda () (sync/timeout 0 p) (channel-put ch 7)))
|
(thread (lambda () (sync/timeout 0 p) (channel-put ch 7)))
|
||||||
|
|
|
@ -5993,6 +5993,8 @@ static Scheme_Object *do_sync(const char *name, int argc, Scheme_Object *argv[],
|
||||||
if (!SCHEME_FALSEP(argv[0])) {
|
if (!SCHEME_FALSEP(argv[0])) {
|
||||||
if (SCHEME_REALP(argv[0]))
|
if (SCHEME_REALP(argv[0]))
|
||||||
timeout = (float)scheme_real_to_double(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) {
|
if (timeout < 0.0) {
|
||||||
scheme_wrong_type(name, "non-negative real number", 0, argc, argv);
|
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;
|
return o;
|
||||||
|
} 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)
|
} else if (tailok)
|
||||||
return scheme_false;
|
return scheme_false;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *sch_sync(int argc, Scheme_Object *argv[])
|
static Scheme_Object *sch_sync(int argc, Scheme_Object *argv[])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user