foreign: document internal make-late-will-executor

Also, rename from "stubborn" to "late" internally to be more
consistent and avoid overloading "stubborn" in the allocator.
This commit is contained in:
Matthew Flatt 2019-05-02 21:52:20 -06:00
parent 032479cf2c
commit e13fac3ccf
16 changed files with 79 additions and 62 deletions

View File

@ -380,7 +380,7 @@ Registers a finalizer procedure @racket[finalizer-proc] with the given
@racket[obj], which can be any Racket (GC-able) object. The finalizer
is registered with a ``late'' @tech[#:doc reference.scrbl]{will
executor} that makes wills ready for a value only after all
@tech[#:doc reference.scrbl]{weak box}es referencing the value have
weak references (such as in a @tech[#:doc reference.scrbl]{weak box}) for the value have
been cleared, which implies that the value is unreachable and no
normal @tech[#:doc reference.scrbl]{will executor} has a will ready
for the value. The finalizer is invoked when the will for @racket[obj]

View File

@ -87,7 +87,24 @@ A curried variant of @racket[ffi-callback] that takes the callback procedure
separately.}
@defproc[(ffi-callback? [x any/c]) boolean?]{
@defproc[(ffi-callback? [v any/c]) boolean?]{
A predicate for callback values that are created by @racket[ffi-callback].
}
@defproc[(make-late-will-executor) will-executor?]{
Creates a ``late'' will executor that readies a will for a value
@scheme[_v] only if no normal will executor has a will registered for
@scheme[_v]. In addition, weak references to @scheme[_v] are cleared
before a will for @racket[_v] is readied by the late will
executor.
Unlike a normal will executor, if a late will executor becomes
inaccessible, the values for which it has pending wills are retained
within the late will executor's place.
A late will executor is intended for use only in the implementation of
@racket[register-finalizer]. See also @racket[make-late-weak-box] and
@racket[make-late-weak-hasheq].}

View File

@ -2062,8 +2062,8 @@
;; We bind `killer-executor' as a location variable, instead of a module
;; variable, so that the loop for `killer-thread' doesn't have a namespace
;; (via a prefix) in its continuation:
(let ([killer-executor (make-stubborn-will-executor)])
;; The "stubborn" kind of will executor (for `killer-executor') is
(let ([killer-executor (make-late-will-executor)])
;; The "late" kind of will executor (for `killer-executor') is
;; provided by '#%foreign, and it doesn't get GC'ed if any
;; finalizers are attached to it (while the normal kind can get
;; GCed even if a thread that is otherwise inaccessible is blocked

View File

@ -62,7 +62,7 @@
[make-late-weak-box (known-procedure 2)]
[make-late-weak-hasheq (known-procedure 1)]
[make-sized-byte-string (known-procedure 4)]
[make-stubborn-will-executor (known-procedure 1)]
[make-late-will-executor (known-procedure 1)]
[make-union-type (known-procedure -2)]
[malloc (known-procedure 62)]
[malloc-immobile-cell (known-procedure 2)]

View File

@ -476,7 +476,7 @@
;; not the same as Racket will executors:
(rename
[make-will-executor rumble:make-will-executor]
[make-stubborn-will-executor rumble:make-stubborn-will-executor]
[make-late-will-executor rumble:make-late-will-executor]
[will-executor? rumble:will-executor?]
[will-register rumble:will-register]
[will-try-execute rumble:will-try-execute])

View File

@ -3,7 +3,7 @@
;; for when a will becomes ready
(define-thread-local the-will-guardian (make-guardian))
(define-thread-local the-stubborn-will-guardian (make-guardian #t))
(define-thread-local the-late-will-guardian (make-guardian #t))
;; Guardian callbacks are called fifo, but will executors are called
;; lifo. The `will-stacks` tables map a finalized value to a list
@ -11,22 +11,22 @@
;; executor with a will function (so that the function is not retained
;; if the will executor is dropped)
(define-thread-local the-will-stacks (make-weak-eq-hashtable))
(define-thread-local the-stubborn-will-stacks (make-weak-eq-hashtable))
(define-thread-local the-late-will-stacks (make-weak-eq-hashtable))
(define-thread-local stubborn-will-executors-with-pending (make-eq-hashtable))
(define-thread-local late-will-executors-with-pending (make-eq-hashtable))
(define-record-type (will-executor create-will-executor will-executor?)
(fields guardian will-stacks (mutable ready) notify stubborn?))
(fields guardian will-stacks (mutable ready) notify late?))
(define (make-will-executor notify)
(create-will-executor the-will-guardian the-will-stacks '() notify #f))
;; A "stubborn" will executor corresponds to an ordered guardian. It
;; A "late" will executor corresponds to an ordered guardian. It
;; doesn't need to make any guarantees about order for multiple
;; registrations, so use a fresh guardian each time.
;; A stubborn executor is treated a little specially in `will-register`.
(define (make-stubborn-will-executor notify)
(create-will-executor the-stubborn-will-guardian the-stubborn-will-stacks '() notify #t))
;; A late executor is treated a little specially in `will-register`.
(define (make-late-will-executor notify)
(create-will-executor the-late-will-guardian the-late-will-stacks '() notify #t))
(define/who (will-register executor v proc)
(check who will-executor? executor)
@ -37,9 +37,9 @@
;; unreachable, then we can drop the finalizer procedure. That
;; pattern prevents unbreakable cycles by an untrusted process
;; that has no access to a will executor that outlives the
;; process. But stubborn will executors persist as long as
;; process. But late will executors persist as long as
;; a will is registered.
[e+proc (if (will-executor-stubborn? executor)
[e+proc (if (will-executor-late? executor)
(cons executor proc)
(ephemeron-cons executor proc))])
(hashtable-set! (will-executor-will-stacks executor) v (cons e+proc l))
@ -58,9 +58,9 @@
(cond
[(pair? l)
(will-executor-ready-set! executor (cdr l))
(when (and (will-executor-stubborn? executor)
(when (and (will-executor-late? executor)
(null? (cdr l)))
(hashtable-delete! stubborn-will-executors-with-pending executor))
(hashtable-delete! late-will-executors-with-pending executor))
(enable-interrupts)
(car l)]
[else
@ -95,12 +95,12 @@
(guardian v)])
((will-executor-notify e))
(will-executor-ready-set! e (cons (cons proc v) (will-executor-ready e)))
(when (will-executor-stubborn? e)
;; Ensure that a stubborn will executor stays live
(when (will-executor-late? e)
;; Ensure that a late will executor stays live
;; in this place as long as there are wills to execute
(hashtable-set! stubborn-will-executors-with-pending e #t))]))))
(hashtable-set! late-will-executors-with-pending e #t))]))))
(loop)))))
(define (poll-will-executors)
(poll-guardian the-will-guardian the-will-stacks)
(poll-guardian the-stubborn-will-guardian the-stubborn-will-stacks))
(poll-guardian the-late-will-guardian the-late-will-stacks))

View File

@ -120,7 +120,7 @@
'set-ctl-c-handler! rumble:set-ctl-c-handler!
'poll-will-executors poll-will-executors
'make-will-executor rumble:make-will-executor
'make-stubborn-will-executor rumble:make-stubborn-will-executor
'make-late-will-executor rumble:make-late-will-executor
'will-executor? rumble:will-executor?
'will-register rumble:will-register
'will-try-execute rumble:will-try-execute

View File

@ -4743,11 +4743,11 @@ static Scheme_Object *foreign_lookup_errno(int argc, Scheme_Object *argv[])
/*****************************************************************************/
/* (make-stubborn-will-executor) -> #<will-executor> */
#define MYNAME "make-stubborn-will-executor"
static Scheme_Object *foreign_make_stubborn_will_executor(int argc, Scheme_Object *argv[])
/* (make-late-will-executor) -> #<will-executor> */
#define MYNAME "make-late-will-executor"
static Scheme_Object *foreign_make_late_will_executor(int argc, Scheme_Object *argv[])
{
return scheme_make_stubborn_will_executor();
return scheme_make_late_will_executor();
}
#undef MYNAME
@ -4988,8 +4988,8 @@ void scheme_init_foreign(Scheme_Startup_Env *env)
scheme_make_immed_prim(foreign_saved_errno, "saved-errno", 0, 1), env);
scheme_addto_prim_instance("lookup-errno",
scheme_make_immed_prim(foreign_lookup_errno, "lookup-errno", 1, 1), env);
scheme_addto_prim_instance("make-stubborn-will-executor",
scheme_make_immed_prim(foreign_make_stubborn_will_executor, "make-stubborn-will-executor", 0, 0), env);
scheme_addto_prim_instance("make-late-will-executor",
scheme_make_immed_prim(foreign_make_late_will_executor, "make-late-will-executor", 0, 0), env);
scheme_addto_prim_instance("make-late-weak-box",
scheme_make_immed_prim(foreign_make_late_weak_box, "make-late-weak-box", 1, 1), env);
scheme_addto_prim_instance("make-late-weak-hasheq",
@ -5246,9 +5246,9 @@ static Scheme_Object *foreign_make_ctype(int argc, Scheme_Object **argv)
return scheme_false;
}
static Scheme_Object *foreign_make_stubborn_will_executor(int argc, Scheme_Object *argv[])
static Scheme_Object *foreign_make_late_will_executor(int argc, Scheme_Object *argv[])
{
return scheme_make_stubborn_will_executor();
return scheme_make_late_will_executor();
}
void scheme_init_foreign(Scheme_Env *env)
@ -5353,8 +5353,8 @@ void scheme_init_foreign(Scheme_Env *env)
scheme_make_immed_prim((Scheme_Prim *)unimplemented, "saved-errno", 0, 1), env);
scheme_addto_primitive_instance("lookup-errno",
scheme_make_immed_prim((Scheme_Prim *)unimplemented, "lookup-errno", 1, 1), env);
scheme_addto_primitive_instance("make-stubborn-will-executor",
scheme_make_immed_prim((Scheme_Prim *)foreign_make_stubborn_will_executor, "make-stubborn-will-executor", 0, 0), env);
scheme_addto_primitive_instance("make-late-will-executor",
scheme_make_immed_prim((Scheme_Prim *)foreign_make_late_will_executor, "make-late-will-executor", 0, 0), env);
scheme_addto_primitive_instance("make-late-weak-box",
scheme_make_immed_prim((Scheme_Prim *)unimplemented, "make-late-weak-box", 1, 1), env);
scheme_addto_primitive_instance("make-late-weak-hasheq",

View File

@ -3660,9 +3660,9 @@ static void save_errno_values(int kind)
/*****************************************************************************/
/* (make-stubborn-will-executor) -> #<will-executor> */
@cdefine[make-stubborn-will-executor 0 #:kind immed]{
return scheme_make_stubborn_will_executor();
/* (make-late-will-executor) -> #<will-executor> */
@cdefine[make-late-will-executor 0 #:kind immed]{
return scheme_make_late_will_executor();
}
/* (make-late-weak-box val) -> #<weak-box> */
@ -3830,15 +3830,15 @@ static Scheme_Object *foreign_make_ctype(int argc, Scheme_Object **argv)
return scheme_false;
}
static Scheme_Object *foreign_make_stubborn_will_executor(int argc, Scheme_Object *argv[])
static Scheme_Object *foreign_make_late_will_executor(int argc, Scheme_Object *argv[])
{
return scheme_make_stubborn_will_executor();
return scheme_make_late_will_executor();
}
@(define (lookup name)
(if (member (cadr name) '("compiler_sizeof"
"make_ctype"
"make_stubborn_will_executor"))
"make_late_will_executor"))
name
'unimplemented))

View File

@ -256,7 +256,7 @@ typedef struct Thread_Local_Variables {
struct Scheme_Config *initial_config_;
struct Scheme_Thread *swap_target_;
struct Scheme_Object *scheduled_kills_;
struct Scheme_Hash_Table *stubborn_will_executors_with_pending_;
struct Scheme_Hash_Table *late_will_executors_with_pending_;
int do_atomic_;
int missed_context_switch_;
int all_breaks_disabled_;
@ -641,7 +641,7 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
#define initial_config XOA (scheme_get_thread_local_variables()->initial_config_)
#define swap_target XOA (scheme_get_thread_local_variables()->swap_target_)
#define scheduled_kills XOA (scheme_get_thread_local_variables()->scheduled_kills_)
#define stubborn_will_executors_with_pending XOA (scheme_get_thread_local_variables()->stubborn_will_executors_with_pending_)
#define late_will_executors_with_pending XOA (scheme_get_thread_local_variables()->late_will_executors_with_pending_)
#define do_atomic XOA (scheme_get_thread_local_variables()->do_atomic_)
#define missed_context_switch XOA (scheme_get_thread_local_variables()->missed_context_switch_)
#define all_breaks_disabled XOA (scheme_get_thread_local_variables()->all_breaks_disabled_)

View File

@ -1142,7 +1142,7 @@ MZ_EXTERN Scheme_Object *scheme_make_ephemeron(Scheme_Object *key, Scheme_Object
MZ_EXTERN Scheme_Object *scheme_ephemeron_value(Scheme_Object *o);
MZ_EXTERN Scheme_Object *scheme_ephemeron_key(Scheme_Object *o);
MZ_EXTERN Scheme_Object *scheme_make_stubborn_will_executor();
MZ_EXTERN Scheme_Object *scheme_make_late_will_executor();
MZ_EXTERN Scheme_Object *scheme_load(const char *file);
MZ_EXTERN Scheme_Object *scheme_load_extension(const char *filename, Scheme_Env *env);

View File

@ -127,7 +127,7 @@ READ_ONLY static Scheme_Object *initial_inspector;
THREAD_LOCAL_DECL(static Scheme_Plumber *initial_plumber);
THREAD_LOCAL_DECL(static Scheme_Hash_Table *stubborn_will_executors_with_pending = NULL);
THREAD_LOCAL_DECL(static Scheme_Hash_Table *late_will_executors_with_pending = NULL);
THREAD_LOCAL_DECL(Scheme_Config *initial_config);
@ -8647,7 +8647,7 @@ typedef struct WillExecutor {
Scheme_Object so;
Scheme_Object *sema;
ActiveWill *first, *last;
int is_stubborn;
int is_late;
} WillExecutor;
static void activate_will(void *o, void *data)
@ -8679,14 +8679,14 @@ static void activate_will(void *o, void *data)
w->last = a;
scheme_post_sema(w->sema);
if (w->is_stubborn) {
/* Ensure that a stubborn will executor stays live in this place
if (w->is_late) {
/* Ensure that a late will executor stays live in this place
as long as there are wills to execute. */
if (!stubborn_will_executors_with_pending) {
REGISTER_SO(stubborn_will_executors_with_pending);
stubborn_will_executors_with_pending = scheme_make_hash_table(SCHEME_hash_ptr);
if (!late_will_executors_with_pending) {
REGISTER_SO(late_will_executors_with_pending);
late_will_executors_with_pending = scheme_make_hash_table(SCHEME_hash_ptr);
}
scheme_hash_set(stubborn_will_executors_with_pending, (Scheme_Object *)w, scheme_true);
scheme_hash_set(late_will_executors_with_pending, (Scheme_Object *)w, scheme_true);
}
}
}
@ -8700,8 +8700,8 @@ static Scheme_Object *do_next_will(WillExecutor *w)
w->first = a->next;
if (!w->first) {
w->last = NULL;
if (w->is_stubborn)
scheme_hash_set(stubborn_will_executors_with_pending, (Scheme_Object *)w, NULL);
if (w->is_late)
scheme_hash_set(late_will_executors_with_pending, (Scheme_Object *)w, NULL);
}
o[0] = a->o;
@ -8722,17 +8722,17 @@ static Scheme_Object *make_will_executor(int argc, Scheme_Object **argv)
w->first = NULL;
w->last = NULL;
w->sema = sema;
w->is_stubborn = 0;
w->is_late = 0;
return (Scheme_Object *)w;
}
Scheme_Object *scheme_make_stubborn_will_executor()
Scheme_Object *scheme_make_late_will_executor()
{
WillExecutor *w;
w = (WillExecutor *)make_will_executor(0, NULL);
w->is_stubborn = 1;
w->is_late = 1;
return (Scheme_Object *)w;
}
@ -8752,7 +8752,7 @@ static Scheme_Object *register_will(int argc, Scheme_Object **argv)
scheme_wrong_contract("will-register", "will-executor?", 0, argc, argv);
scheme_check_proc_arity("will-register", 1, 2, argc, argv);
if (((WillExecutor *)argv[0])->is_stubborn) {
if (((WillExecutor *)argv[0])->is_late) {
e = scheme_make_pair(argv[0], argv[2]);
scheme_add_finalizer(argv[1], activate_will, e);
} else {

View File

@ -102,7 +102,7 @@
[(custodian-shut-down? cust) #f]
[else
(define we (and (not weak?)
(host:make-stubborn-will-executor void)))
(host:make-late-will-executor void)))
(hash-set! (custodian-children cust)
obj
(cond

View File

@ -44,7 +44,7 @@
[poll-will-executors host:poll-will-executors]
[make-will-executor host:make-will-executor]
[make-stubborn-will-executor host:make-stubborn-will-executor]
[make-late-will-executor host:make-late-will-executor]
[will-executor? host:will-executor?]
[will-register host:will-register]
[will-try-execute host:will-try-execute]

View File

@ -122,7 +122,7 @@
custodian-shut-down?
make-will-executor
make-stubborn-will-executor
make-late-will-executor
will-executor?
will-register
will-try-execute

View File

@ -10,7 +10,7 @@
;; `will-execute` here, because it has to block when no will is ready.
(provide make-will-executor
make-stubborn-will-executor
make-late-will-executor
will-executor?
will-register
will-try-execute
@ -35,8 +35,8 @@
;; The returned wrapper will executor isn't necessarily retained when
;; there are pending wills, but the underlying one is retained, and
;; that implies that finalized values won't get lost
(define (make-stubborn-will-executor)
(do-make-will-executor host:make-stubborn-will-executor))
(define (make-late-will-executor)
(do-make-will-executor host:make-late-will-executor))
(define/who (will-register we v proc)
(check who will-executor? we)