diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-03-23 06:31:10 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-03-23 06:31:10 -0700 |
commit | 37e5a84d7483a6f323d7f069ac3b33ecd0c9d8e7 (patch) | |
tree | 999c63b21968ea22b68d69df43b9405c810fae99 /txr.1 | |
parent | b629707890bf3f527f1d33a17815ef214ee6dc39 (diff) | |
download | txr-37e5a84d7483a6f323d7f069ac3b33ecd0c9d8e7.tar.gz txr-37e5a84d7483a6f323d7f069ac3b33ecd0c9d8e7.tar.bz2 txr-37e5a84d7483a6f323d7f069ac3b33ecd0c9d8e7.zip |
call-finalizers: allow recursion.
Code to invoke finalizers and remove them from the
list is consolidated: both the gc and call-finalizers
now use the same lower-level function.
Finalizers may now themselves call-finalizers; it is no longer
"unspecified behavior". This greatly improves the the TXR Lisp
support for RAII, since :fini handlers of objects can call
finalization on related objects. For instance a container
being finalized can call the finalizers of contained objects.
* gc.c (call_finalizers_impl): New function. Gathers all
eligible finalizer registrations into a local list,
first, removing them from the global list. Then does the
calls in a second pass. Also, relative to the original
functions which it replaces, this fixes an incorrect case:
when the list is of length 1 and contains an eligible
entry, in which case the global final_tail pointer is left
aiming at a local variable!
(is_reachable_final): New static function.
(call_finalizers): Use call_finalizers_impl, specifying
is_reachable_final as the predicate.
(is_matching_final): New static function.
(gc_call_finalizers): Use call_finalizers_impl, specifying
is_matching_final as the predicate.
* txr.1: Update documentation about call-finalizers.
Diffstat (limited to 'txr.1')
-rw-r--r-- | txr.1 | 36 |
1 files changed, 35 insertions, 1 deletions
@@ -51335,8 +51335,42 @@ If any finalizers are called, it returns otherwise .codn nil . -Note: the behavior is unspecified if a finalizer function calls +It is permissible for a finalizer function itself to call .codn call-finalizers . +Such a call can happen in two possible contexts: during actual +reclamation driven by garbage collection, or under the scope of a +.code call-finalizers +invocation from application code. + +Under the scope of garbage-collection-driven reclamation, the +order of finalizer calls may not be what the application logic +expects. For instance even though a finalizer registered for some object +.code A +itself invokes +.codn "(call-finalizers B)" , +it may be the case during GC reclamation that both +.code A +and +.code B +are identified as unreachable objects at the same time, and some or all +finalizers registered against +.code B +have already been called before the given +.code A +finalizer performs the explicit +.code call-finalizers +invocation against +.codn B . +Thus the the call either has no effect at all, or only calls some remaining +.code B +finalizers that have not yet been processed, rather than all of them, +as the application expects. + +The application must avoid creating a dependency on the order of +finalization calls, to prevent the situation that the finalization actions are +only correct under an explicit +.code call-finalizers +but incorrect under spontaneous reclamation driven by garbage collection. .SS* Modularization .coNP Variable @ self-path |