fix unsafe-poller
result handling and improve docs
This commit is contained in:
parent
544b7a3d53
commit
5ad28e8942
|
@ -6,7 +6,9 @@
|
|||
|
||||
@defmodule[ffi/unsafe/schedule]{The
|
||||
@racketmodname[ffi/unsafe/schedule] library provides functions for
|
||||
cooperating with the thread scheduler and manipulating it.}
|
||||
cooperating with the thread scheduler and manipulating it. These
|
||||
operations are unsafe because callbacks run in @tech{atomic mode}
|
||||
and in an unspecified thread.}
|
||||
|
||||
@history[#:added "6.11.0.1"]
|
||||
|
||||
|
@ -16,8 +18,8 @@ cooperating with the thread scheduler and manipulating it.}
|
|||
Produces a @deftech{poller} value that is allowed as a
|
||||
@racket[prop:evt] value, even though it is not a procedure or itself
|
||||
an @racket[evt?]. The @racket[poll] callback is called in @tech{atomic
|
||||
mode} to check whether the event is ready or to allow it to register a
|
||||
wakeup trigger.
|
||||
mode} in an unspecified thread to check whether the event is ready or
|
||||
to allow it to register a wakeup trigger.
|
||||
|
||||
The first argument to @racket[poll] is always the object that is used
|
||||
as a @tech[#:doc reference.scrbl]{synchronizable event} with the
|
||||
|
@ -74,14 +76,6 @@ Causes the Racket process will wake up and resume polling at the point
|
|||
when @racket[(current-inexact-milliseconds)] starts returning a value
|
||||
that is @racket[msecs] or greater.}
|
||||
|
||||
|
||||
Registers a file descriptor (Unix and Mac OS) or socket (all
|
||||
platforms) to cause the Racket process to wake up if the file
|
||||
descriptor or socket becomes ready for reading, writing, or error
|
||||
reporting, as selected by @racket[mode]. The @racket[wakeups] argument
|
||||
must be a non-@racket[#f] value that is passed by the scheduler to a
|
||||
@racket[unsafe-poller]-wrapped procedure.}
|
||||
|
||||
@defproc[(unsafe-set-sleep-in-thread! [foreground-sleep (-> any/c)]
|
||||
[fd fixnum?])
|
||||
void?]{
|
||||
|
@ -101,6 +95,6 @@ Racket implementation. It always works for Mac OS.}
|
|||
@defproc[(unsafe-signal-received) void?]{
|
||||
|
||||
For use with @racket[unsafe-set-sleep-in-thread!] by
|
||||
@racket[foreground-sleep] or something that it triggers, causes the
|
||||
default sleeping function to request @racket[foreground-sleep] to
|
||||
@racket[_foreground-sleep] or something that it triggers, causes the
|
||||
default sleeping function to request @racket[_foreground-sleep] to
|
||||
return.}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#lang scribble/doc
|
||||
@(require scribble/struct
|
||||
"mz.rkt"
|
||||
(for-label racket/async-channel))
|
||||
(for-label racket/async-channel
|
||||
(only-in ffi/unsafe/schedule unsafe-poller)))
|
||||
|
||||
@(define evt-eval (make-base-eval))
|
||||
|
||||
|
@ -355,6 +356,11 @@ A @tech{structure type property} that identifies structure types whose
|
|||
|
||||
]
|
||||
|
||||
@margin-note{For working with foreign libraries, a @racket[prop:evt]
|
||||
value can also be a result of @racket[unsafe-poller],
|
||||
although that possibility is omitted from the safe
|
||||
contract of @racket[prop:evt].}
|
||||
|
||||
Instances of a structure type with the @racket[prop:input-port] or
|
||||
@racket[prop:output-port] property are also @tech{synchronizable events} by virtue
|
||||
of being a port. If the structure type has more than one of
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
|
||||
|
||||
(load-relative "loadtest.rktl")
|
||||
|
||||
(require ffi/unsafe/schedule)
|
||||
|
||||
(Section 'synchronization)
|
||||
|
||||
(define SYNC-SLEEP-DELAY 0.025)
|
||||
|
@ -973,6 +974,37 @@
|
|||
;; make sure it's ok for rewind to be the first action:
|
||||
(test (void) thread-wait (thread (lambda () (thread-rewind-receive '(1 2 3)))))
|
||||
|
||||
;; ----------------------------------------
|
||||
;; Unsafe poller
|
||||
|
||||
(let ()
|
||||
(struct p (results)
|
||||
#:property prop:evt (unsafe-poller
|
||||
(lambda (self wakeups)
|
||||
(values (p-results self) #f))))
|
||||
|
||||
(test 17 sync (p '(17)))
|
||||
(test add1 sync (p (list add1)))
|
||||
(test-values '(16 17) (lambda () (sync (p '(16 17)))))
|
||||
(test-values '() (lambda () (sync (p '())))))
|
||||
|
||||
(let ()
|
||||
;; Let the scheduler poll up to `counter` times:
|
||||
(define counter 20)
|
||||
(struct p ()
|
||||
#:property prop:evt (unsafe-poller
|
||||
(lambda (self wakeups)
|
||||
(cond
|
||||
[(zero? counter)
|
||||
(values '(#t) #f)]
|
||||
[else
|
||||
(set! counter (sub1 counter))
|
||||
(when wakeups
|
||||
;; Cancel any sleep:
|
||||
(unsafe-poll-ctx-milliseconds-wakeup wakeups (current-inexact-milliseconds)))
|
||||
(values #f self)]))))
|
||||
(test #t sync (p)))
|
||||
|
||||
;; ----------------------------------------
|
||||
;; Garbage collection
|
||||
|
||||
|
|
|
@ -1646,6 +1646,21 @@ static Scheme_Object *return_wrapped(void *data, int argc, Scheme_Object *argv[]
|
|||
return (Scheme_Object *)data;
|
||||
}
|
||||
|
||||
static Scheme_Object *return_wrapped_multi(void *data, int argc, Scheme_Object *argv[])
|
||||
{
|
||||
Scheme_Object **a, *l = (Scheme_Object *)data;
|
||||
int i, n;
|
||||
|
||||
n = scheme_list_length(l);
|
||||
a = MALLOC_N(Scheme_Object *, n);
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i] = SCHEME_CAR(l);
|
||||
l = SCHEME_CDR(l);
|
||||
}
|
||||
|
||||
return scheme_values(n, a);
|
||||
}
|
||||
|
||||
static int evt_struct_is_ready(Scheme_Object *o, Scheme_Schedule_Info *sinfo)
|
||||
{
|
||||
Scheme_Object *v;
|
||||
|
@ -1731,8 +1746,19 @@ static int evt_struct_is_ready(Scheme_Object *o, Scheme_Schedule_Info *sinfo)
|
|||
scheme_end_in_scheduler();
|
||||
|
||||
if (v) {
|
||||
if (done && SCHEME_PROCP(v)) {
|
||||
v = scheme_make_closed_prim_w_arity(return_wrapped, (void *)v, "wrapper", 1, 1);
|
||||
if (done) {
|
||||
int check_proc = 1;
|
||||
if (SCHEME_PAIRP(v) && SCHEME_NULLP(SCHEME_CDR(v)) && !SCHEME_PROCP(SCHEME_CAR(v)))
|
||||
v = SCHEME_CAR(v); /* single result */
|
||||
else if (!SCHEME_NULLP(v) && !SCHEME_PAIRP(v)) {
|
||||
/* wrong result, be we allow it for backward compatibility */
|
||||
} else {
|
||||
v = scheme_make_closed_prim_w_arity(return_wrapped_multi, (void *)v, "multi-wrapper", 1, 1);
|
||||
check_proc = 0;
|
||||
}
|
||||
|
||||
if (check_proc && SCHEME_PROCP(v))
|
||||
v = scheme_make_closed_prim_w_arity(return_wrapped, (void *)v, "wrapper", 1, 1);
|
||||
}
|
||||
scheme_set_sync_target(sinfo, v, (done ? v : NULL), NULL, 0, 0, NULL);
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue
Block a user