From 37e5a84d7483a6f323d7f069ac3b33ecd0c9d8e7 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 23 Mar 2017 06:31:10 -0700 Subject: 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. --- txr.1 | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'txr.1') diff --git a/txr.1 b/txr.1 index ec45060f..18816b61 100644 --- a/txr.1 +++ b/txr.1 @@ -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 -- cgit v1.2.3