16.3 Wills and Executors
A will executor manages a collection of values and
associated will procedures
(a.k.a. finalizers). The will procedure for each
value is ready to be executed when the value has been proven (by the
garbage collector) to be unreachable, except through weak references
(see Weak Boxes) or as the registrant for other will
executors. A will is useful for triggering clean-up actions on
data associated with an unreachable value, such as closing a port
embedded in an object when the object is no longer used.
Calling the will-execute or will-try-execute
procedure executes a will that is ready in the specified will
executor. A will executor is also a synchronizable event, so sync
or sync/timeout can be used to detect when a will executor has
ready wills. Wills are not executed automatically, because certain
programs need control to avoid race conditions. However, a program can
create a thread whose sole job is to execute wills for a particular
If a value is registered with multiple wills (in one or multiple
executors), the wills are readied in the reverse order of
registration. Since readying a will procedure makes the value
reachable again, the will must be executed and the value must be
proven again unreachable through only weak references before another
of the wills is readied or executed. However, wills for distinct
unreachable values are readied at the same time, regardless of whether
the values are reachable from each other.
A will executor’s register is held non-weakly until after the
corresponding will procedure is executed. Thus, if the content value
of a weak box (see Weak Boxes) is registered with a will
executor, the weak box’s content is not changed to #f until
all wills have been executed for the value and the value has been
proven again reachable through only weak references.
A will executor can be used as a synchronizable event (see Events).
A will executor is ready for synchronization when
will-execute would not block; the synchronization result of a will executor is the will executor itself.
These examples show how to run cleanup actions when
no synchronization is necessary. It simply runs the registered
executors as they become ready in another thread.
Returns a new will executor with no managed values.
Returns #t if v is a will executor, #f
Registers the value v
with the will procedure proc
in the will executor executor
. When v
unreachable, then the procedure proc
is ready to be called
as its argument via will-execute
. The proc
argument is strongly
referenced until the will procedure is executed.
Invokes the will procedure for a single “unreachable” value
registered with the executor executor
. The values returned
by the will procedure are the result of the will-execute
call. If no will is ready for immediate execution,
blocks until one is ready.
if a will is ready for immediate
execution. Otherwise, #f