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 @racket[obj], which can be any Racket (GC-able) object. The finalizer
is registered with a ``late'' @tech[#:doc reference.scrbl]{will is registered with a ``late'' @tech[#:doc reference.scrbl]{will
executor} that makes wills ready for a value only after all 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 been cleared, which implies that the value is unreachable and no
normal @tech[#:doc reference.scrbl]{will executor} has a will ready normal @tech[#:doc reference.scrbl]{will executor} has a will ready
for the value. The finalizer is invoked when the will for @racket[obj] 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.} 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]. 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 ;; 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 ;; variable, so that the loop for `killer-thread' doesn't have a namespace
;; (via a prefix) in its continuation: ;; (via a prefix) in its continuation:
(let ([killer-executor (make-stubborn-will-executor)]) (let ([killer-executor (make-late-will-executor)])
;; The "stubborn" kind of will executor (for `killer-executor') is ;; The "late" kind of will executor (for `killer-executor') is
;; provided by '#%foreign, and it doesn't get GC'ed if any ;; provided by '#%foreign, and it doesn't get GC'ed if any
;; finalizers are attached to it (while the normal kind can get ;; finalizers are attached to it (while the normal kind can get
;; GCed even if a thread that is otherwise inaccessible is blocked ;; 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-box (known-procedure 2)]
[make-late-weak-hasheq (known-procedure 1)] [make-late-weak-hasheq (known-procedure 1)]
[make-sized-byte-string (known-procedure 4)] [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)] [make-union-type (known-procedure -2)]
[malloc (known-procedure 62)] [malloc (known-procedure 62)]
[malloc-immobile-cell (known-procedure 2)] [malloc-immobile-cell (known-procedure 2)]

View File

@ -476,7 +476,7 @@
;; not the same as Racket will executors: ;; not the same as Racket will executors:
(rename (rename
[make-will-executor rumble:make-will-executor] [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-executor? rumble:will-executor?]
[will-register rumble:will-register] [will-register rumble:will-register]
[will-try-execute rumble:will-try-execute]) [will-try-execute rumble:will-try-execute])

View File

@ -3,7 +3,7 @@
;; for when a will becomes ready ;; for when a will becomes ready
(define-thread-local the-will-guardian (make-guardian)) (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 ;; Guardian callbacks are called fifo, but will executors are called
;; lifo. The `will-stacks` tables map a finalized value to a list ;; 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 ;; executor with a will function (so that the function is not retained
;; if the will executor is dropped) ;; if the will executor is dropped)
(define-thread-local the-will-stacks (make-weak-eq-hashtable)) (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?) (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) (define (make-will-executor notify)
(create-will-executor the-will-guardian the-will-stacks '() notify #f)) (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 ;; doesn't need to make any guarantees about order for multiple
;; registrations, so use a fresh guardian each time. ;; registrations, so use a fresh guardian each time.
;; A stubborn executor is treated a little specially in `will-register`. ;; A late executor is treated a little specially in `will-register`.
(define (make-stubborn-will-executor notify) (define (make-late-will-executor notify)
(create-will-executor the-stubborn-will-guardian the-stubborn-will-stacks '() notify #t)) (create-will-executor the-late-will-guardian the-late-will-stacks '() notify #t))
(define/who (will-register executor v proc) (define/who (will-register executor v proc)
(check who will-executor? executor) (check who will-executor? executor)
@ -37,9 +37,9 @@
;; unreachable, then we can drop the finalizer procedure. That ;; unreachable, then we can drop the finalizer procedure. That
;; pattern prevents unbreakable cycles by an untrusted process ;; pattern prevents unbreakable cycles by an untrusted process
;; that has no access to a will executor that outlives the ;; 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. ;; a will is registered.
[e+proc (if (will-executor-stubborn? executor) [e+proc (if (will-executor-late? executor)
(cons executor proc) (cons executor proc)
(ephemeron-cons executor proc))]) (ephemeron-cons executor proc))])
(hashtable-set! (will-executor-will-stacks executor) v (cons e+proc l)) (hashtable-set! (will-executor-will-stacks executor) v (cons e+proc l))
@ -58,9 +58,9 @@
(cond (cond
[(pair? l) [(pair? l)
(will-executor-ready-set! executor (cdr l)) (will-executor-ready-set! executor (cdr l))
(when (and (will-executor-stubborn? executor) (when (and (will-executor-late? executor)
(null? (cdr l))) (null? (cdr l)))
(hashtable-delete! stubborn-will-executors-with-pending executor)) (hashtable-delete! late-will-executors-with-pending executor))
(enable-interrupts) (enable-interrupts)
(car l)] (car l)]
[else [else
@ -95,12 +95,12 @@
(guardian v)]) (guardian v)])
((will-executor-notify e)) ((will-executor-notify e))
(will-executor-ready-set! e (cons (cons proc v) (will-executor-ready e))) (will-executor-ready-set! e (cons (cons proc v) (will-executor-ready e)))
(when (will-executor-stubborn? e) (when (will-executor-late? e)
;; Ensure that a stubborn will executor stays live ;; Ensure that a late will executor stays live
;; in this place as long as there are wills to execute ;; 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))))) (loop)))))
(define (poll-will-executors) (define (poll-will-executors)
(poll-guardian the-will-guardian the-will-stacks) (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! 'set-ctl-c-handler! rumble:set-ctl-c-handler!
'poll-will-executors poll-will-executors 'poll-will-executors poll-will-executors
'make-will-executor rumble:make-will-executor '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-executor? rumble:will-executor?
'will-register rumble:will-register 'will-register rumble:will-register
'will-try-execute rumble:will-try-execute '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> */ /* (make-late-will-executor) -> #<will-executor> */
#define MYNAME "make-stubborn-will-executor" #define MYNAME "make-late-will-executor"
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();
} }
#undef MYNAME #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_make_immed_prim(foreign_saved_errno, "saved-errno", 0, 1), env);
scheme_addto_prim_instance("lookup-errno", scheme_addto_prim_instance("lookup-errno",
scheme_make_immed_prim(foreign_lookup_errno, "lookup-errno", 1, 1), env); scheme_make_immed_prim(foreign_lookup_errno, "lookup-errno", 1, 1), env);
scheme_addto_prim_instance("make-stubborn-will-executor", scheme_addto_prim_instance("make-late-will-executor",
scheme_make_immed_prim(foreign_make_stubborn_will_executor, "make-stubborn-will-executor", 0, 0), env); 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_addto_prim_instance("make-late-weak-box",
scheme_make_immed_prim(foreign_make_late_weak_box, "make-late-weak-box", 1, 1), env); scheme_make_immed_prim(foreign_make_late_weak_box, "make-late-weak-box", 1, 1), env);
scheme_addto_prim_instance("make-late-weak-hasheq", 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; 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) 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_make_immed_prim((Scheme_Prim *)unimplemented, "saved-errno", 0, 1), env);
scheme_addto_primitive_instance("lookup-errno", scheme_addto_primitive_instance("lookup-errno",
scheme_make_immed_prim((Scheme_Prim *)unimplemented, "lookup-errno", 1, 1), env); scheme_make_immed_prim((Scheme_Prim *)unimplemented, "lookup-errno", 1, 1), env);
scheme_addto_primitive_instance("make-stubborn-will-executor", scheme_addto_primitive_instance("make-late-will-executor",
scheme_make_immed_prim((Scheme_Prim *)foreign_make_stubborn_will_executor, "make-stubborn-will-executor", 0, 0), env); 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_addto_primitive_instance("make-late-weak-box",
scheme_make_immed_prim((Scheme_Prim *)unimplemented, "make-late-weak-box", 1, 1), env); scheme_make_immed_prim((Scheme_Prim *)unimplemented, "make-late-weak-box", 1, 1), env);
scheme_addto_primitive_instance("make-late-weak-hasheq", 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> */ /* (make-late-will-executor) -> #<will-executor> */
@cdefine[make-stubborn-will-executor 0 #:kind immed]{ @cdefine[make-late-will-executor 0 #:kind immed]{
return scheme_make_stubborn_will_executor(); return scheme_make_late_will_executor();
} }
/* (make-late-weak-box val) -> #<weak-box> */ /* (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; 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) @(define (lookup name)
(if (member (cadr name) '("compiler_sizeof" (if (member (cadr name) '("compiler_sizeof"
"make_ctype" "make_ctype"
"make_stubborn_will_executor")) "make_late_will_executor"))
name name
'unimplemented)) 'unimplemented))

View File

@ -256,7 +256,7 @@ typedef struct Thread_Local_Variables {
struct Scheme_Config *initial_config_; struct Scheme_Config *initial_config_;
struct Scheme_Thread *swap_target_; struct Scheme_Thread *swap_target_;
struct Scheme_Object *scheduled_kills_; 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 do_atomic_;
int missed_context_switch_; int missed_context_switch_;
int all_breaks_disabled_; 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 initial_config XOA (scheme_get_thread_local_variables()->initial_config_)
#define swap_target XOA (scheme_get_thread_local_variables()->swap_target_) #define swap_target XOA (scheme_get_thread_local_variables()->swap_target_)
#define scheduled_kills XOA (scheme_get_thread_local_variables()->scheduled_kills_) #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 do_atomic XOA (scheme_get_thread_local_variables()->do_atomic_)
#define missed_context_switch XOA (scheme_get_thread_local_variables()->missed_context_switch_) #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_) #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_value(Scheme_Object *o);
MZ_EXTERN Scheme_Object *scheme_ephemeron_key(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(const char *file);
MZ_EXTERN Scheme_Object *scheme_load_extension(const char *filename, Scheme_Env *env); 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_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); THREAD_LOCAL_DECL(Scheme_Config *initial_config);
@ -8647,7 +8647,7 @@ typedef struct WillExecutor {
Scheme_Object so; Scheme_Object so;
Scheme_Object *sema; Scheme_Object *sema;
ActiveWill *first, *last; ActiveWill *first, *last;
int is_stubborn; int is_late;
} WillExecutor; } WillExecutor;
static void activate_will(void *o, void *data) static void activate_will(void *o, void *data)
@ -8679,14 +8679,14 @@ static void activate_will(void *o, void *data)
w->last = a; w->last = a;
scheme_post_sema(w->sema); scheme_post_sema(w->sema);
if (w->is_stubborn) { if (w->is_late) {
/* Ensure that a stubborn will executor stays live in this place /* Ensure that a late will executor stays live in this place
as long as there are wills to execute. */ as long as there are wills to execute. */
if (!stubborn_will_executors_with_pending) { if (!late_will_executors_with_pending) {
REGISTER_SO(stubborn_will_executors_with_pending); REGISTER_SO(late_will_executors_with_pending);
stubborn_will_executors_with_pending = scheme_make_hash_table(SCHEME_hash_ptr); 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; w->first = a->next;
if (!w->first) { if (!w->first) {
w->last = NULL; w->last = NULL;
if (w->is_stubborn) if (w->is_late)
scheme_hash_set(stubborn_will_executors_with_pending, (Scheme_Object *)w, NULL); scheme_hash_set(late_will_executors_with_pending, (Scheme_Object *)w, NULL);
} }
o[0] = a->o; o[0] = a->o;
@ -8722,17 +8722,17 @@ static Scheme_Object *make_will_executor(int argc, Scheme_Object **argv)
w->first = NULL; w->first = NULL;
w->last = NULL; w->last = NULL;
w->sema = sema; w->sema = sema;
w->is_stubborn = 0; w->is_late = 0;
return (Scheme_Object *)w; return (Scheme_Object *)w;
} }
Scheme_Object *scheme_make_stubborn_will_executor() Scheme_Object *scheme_make_late_will_executor()
{ {
WillExecutor *w; WillExecutor *w;
w = (WillExecutor *)make_will_executor(0, NULL); w = (WillExecutor *)make_will_executor(0, NULL);
w->is_stubborn = 1; w->is_late = 1;
return (Scheme_Object *)w; 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_wrong_contract("will-register", "will-executor?", 0, argc, argv);
scheme_check_proc_arity("will-register", 1, 2, 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]); e = scheme_make_pair(argv[0], argv[2]);
scheme_add_finalizer(argv[1], activate_will, e); scheme_add_finalizer(argv[1], activate_will, e);
} else { } else {

View File

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

View File

@ -44,7 +44,7 @@
[poll-will-executors host:poll-will-executors] [poll-will-executors host:poll-will-executors]
[make-will-executor host:make-will-executor] [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-executor? host:will-executor?]
[will-register host:will-register] [will-register host:will-register]
[will-try-execute host:will-try-execute] [will-try-execute host:will-try-execute]

View File

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

View File

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