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
|
@defmodule[ffi/unsafe/schedule]{The
|
||||||
@racketmodname[ffi/unsafe/schedule] library provides functions for
|
@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"]
|
@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
|
Produces a @deftech{poller} value that is allowed as a
|
||||||
@racket[prop:evt] value, even though it is not a procedure or itself
|
@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
|
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
|
mode} in an unspecified thread to check whether the event is ready or
|
||||||
wakeup trigger.
|
to allow it to register a wakeup trigger.
|
||||||
|
|
||||||
The first argument to @racket[poll] is always the object that is used
|
The first argument to @racket[poll] is always the object that is used
|
||||||
as a @tech[#:doc reference.scrbl]{synchronizable event} with the
|
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
|
when @racket[(current-inexact-milliseconds)] starts returning a value
|
||||||
that is @racket[msecs] or greater.}
|
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)]
|
@defproc[(unsafe-set-sleep-in-thread! [foreground-sleep (-> any/c)]
|
||||||
[fd fixnum?])
|
[fd fixnum?])
|
||||||
void?]{
|
void?]{
|
||||||
|
@ -101,6 +95,6 @@ Racket implementation. It always works for Mac OS.}
|
||||||
@defproc[(unsafe-signal-received) void?]{
|
@defproc[(unsafe-signal-received) void?]{
|
||||||
|
|
||||||
For use with @racket[unsafe-set-sleep-in-thread!] by
|
For use with @racket[unsafe-set-sleep-in-thread!] by
|
||||||
@racket[foreground-sleep] or something that it triggers, causes the
|
@racket[_foreground-sleep] or something that it triggers, causes the
|
||||||
default sleeping function to request @racket[foreground-sleep] to
|
default sleeping function to request @racket[_foreground-sleep] to
|
||||||
return.}
|
return.}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#lang scribble/doc
|
#lang scribble/doc
|
||||||
@(require scribble/struct
|
@(require scribble/struct
|
||||||
"mz.rkt"
|
"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))
|
@(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
|
Instances of a structure type with the @racket[prop:input-port] or
|
||||||
@racket[prop:output-port] property are also @tech{synchronizable events} by virtue
|
@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
|
of being a port. If the structure type has more than one of
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
(load-relative "loadtest.rktl")
|
(load-relative "loadtest.rktl")
|
||||||
|
|
||||||
|
(require ffi/unsafe/schedule)
|
||||||
|
|
||||||
(Section 'synchronization)
|
(Section 'synchronization)
|
||||||
|
|
||||||
(define SYNC-SLEEP-DELAY 0.025)
|
(define SYNC-SLEEP-DELAY 0.025)
|
||||||
|
@ -973,6 +974,37 @@
|
||||||
;; make sure it's ok for rewind to be the first action:
|
;; make sure it's ok for rewind to be the first action:
|
||||||
(test (void) thread-wait (thread (lambda () (thread-rewind-receive '(1 2 3)))))
|
(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
|
;; Garbage collection
|
||||||
|
|
||||||
|
|
|
@ -1646,6 +1646,21 @@ static Scheme_Object *return_wrapped(void *data, int argc, Scheme_Object *argv[]
|
||||||
return (Scheme_Object *)data;
|
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)
|
static int evt_struct_is_ready(Scheme_Object *o, Scheme_Schedule_Info *sinfo)
|
||||||
{
|
{
|
||||||
Scheme_Object *v;
|
Scheme_Object *v;
|
||||||
|
@ -1731,8 +1746,19 @@ static int evt_struct_is_ready(Scheme_Object *o, Scheme_Schedule_Info *sinfo)
|
||||||
scheme_end_in_scheduler();
|
scheme_end_in_scheduler();
|
||||||
|
|
||||||
if (v) {
|
if (v) {
|
||||||
if (done && SCHEME_PROCP(v)) {
|
if (done) {
|
||||||
v = scheme_make_closed_prim_w_arity(return_wrapped, (void *)v, "wrapper", 1, 1);
|
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);
|
scheme_set_sync_target(sinfo, v, (done ? v : NULL), NULL, 0, 0, NULL);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user