summaryrefslogtreecommitdiffstats
path: root/txr.1
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-01-01 02:31:39 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-01-01 02:31:39 -0800
commit3edc515f91586cb5bb7bc666fb9222c67eabfdb2 (patch)
tree76aaba7401a703e7f30f38d47b507c3f3203ec38 /txr.1
parent6bd452f024f0e60ef8a3994d371e13d3469db1cc (diff)
downloadtxr-3edc515f91586cb5bb7bc666fb9222c67eabfdb2.tar.gz
txr-3edc515f91586cb5bb7bc666fb9222c67eabfdb2.tar.bz2
txr-3edc515f91586cb5bb7bc666fb9222c67eabfdb2.zip
gc: do finalizers completely on one phase.
* gc.c (call_finalizers_impl): Iterate over the finalizer registrations until no more finalizers are identified, performing additional rounds, as necessary. Thus if finalizers register more finalizers that are eligible for processing according to the criteria of he current phase, those are done in the current phase. (gc_finalize): We must now carefully set the reachable flag to 1 for a new finalization entry. This was always the right thing to do and is logically correct: if an object is being passed to finalize, it is necessarily reachable. Leaving the 0 initialization would do bad things now, as follows. If any object whatsoever has a finalizer registered against it during GC-driven finalization, its finalizer will be called. This is bad if the object isn't garbage. Secondly, the object may be moved into generation 0, and put into the freshobj list. This is extremely bad if the object is reachable by generation 1 objects, which is now a wrong-way reference. * txr.1: Updated.
Diffstat (limited to 'txr.1')
-rw-r--r--txr.130
1 files changed, 24 insertions, 6 deletions
diff --git a/txr.1 b/txr.1
index 771d8863..3ce278ac 100644
--- a/txr.1
+++ b/txr.1
@@ -66814,9 +66814,17 @@ A finalizer is itself permitted to call
.code finalize
to register the original
.code object
-or any other object for finalization. Such registrations made during
-finalization execution are not eligible for the current phase of finalization
-processing; they will be processed in a later garbage collection pass.
+or any other object for finalization. Finalization processing can be
+understood as taking place in one or more rounds. At the start of each round,
+finalizers are identified that are to be called, arranged in order, and removed
+from the registration list. If this identification stage produces no
+finalizers, then finalization ends. Otherwise, those finalizers are processed,
+and then another round is initiated, to look for finalizers that may have been
+registered during the previous round.
+
+Note: it is possible for the application to create an infinite finalization
+loop, if one or more objects have finalizers that register new finalizers,
+which register new finalizers and so on.
.coNP Function @ call-finalizers
.synb
@@ -66832,12 +66840,22 @@ If any finalizers are called, it returns
otherwise
.codn nil .
+Finalization performed by
+.code call-finalizers
+works in the manner described under the specification of he
+.code finalize
+function.
+
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
+Such a call can happen in two possible contexts: finalization
+initiated by by garbage collection, or under the scope of a
.code call-finalizers
-invocation from application code.
+invocation from application code. Doing so is safe, since the finalization
+logic may be re-entered recursively. When finalizers are being called during a
+round of processing, those finalizers have already been removed from the
+registration list, and will not be redundantly invoked by a recursive
+invocation of finalization.
Under the scope of garbage-collection-driven reclamation, the
order of finalizer calls may not be what the application logic