summary refs log tree commit diff stats
path: root/doc/destructors.rst
diff options
context:
space:
mode:
authorGordonBGood <GordonBGood@users.noreply.github.com>2021-07-15 19:35:53 +0700
committerGitHub <noreply@github.com>2021-07-15 14:35:53 +0200
commit8c6dd2b9a9157c0e0bd822d8a80d1014fc87ecd7 (patch)
tree64de2f80265b0625334439cc9020e89276dd6db5 /doc/destructors.rst
parenta6ff6e7871d757821ba2b84cb8f175f48721bb9a (diff)
downloadNim-8c6dd2b9a9157c0e0bd822d8a80d1014fc87ecd7.tar.gz
Improve description of how =trace is used (#18491)
* [skip ci] thamming_orc test created/destroyed counts match

The thamming_orc.nim code now counts all created objects being tested, not just the ones following the "first 20" test, and the position of the `destroyed += 1` counter has been adjusted so it counts all the calls that are as a result of `=trace` tracing and not just the original destruction calls.

* Improve description of how `=trace` is used

The following nuances weren't previously fully explained:

1. That `=trace` is only used by `--gc:orc`.
2. That `=trace` is almost certainly used along with `=destroy` when manual resource allocation has been used, but it is only required if there is a possibility of cyclic references in the wrapped types (ie. generic types).
3. That, currently, a forward definition is required for the second of the pair to avoid an auto compiler generation conflict.

The pattern of the use of `=trace` has also been made more extensive, showing how both a custom `=destroy` and `=trace` are used for manual allocation of resources when there is any possibility of a cyclic reference in the resource-wrapped values.

* Update doc/destructors.rst

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Diffstat (limited to 'doc/destructors.rst')
-rw-r--r--doc/destructors.rst27
1 files changed, 22 insertions, 5 deletions
diff --git a/doc/destructors.rst b/doc/destructors.rst
index a94ccb9e7..a3fd7514e 100644
--- a/doc/destructors.rst
+++ b/doc/destructors.rst
@@ -222,16 +222,33 @@ The prototype of this hook for a type `T` needs to be:
 `env` is used by ORC to keep track of its internal state, it should be passed around
 to calls of the built-in `=trace` operation.
 
-The general pattern in `=trace` looks like:
+Usually there will only be a need for a custom `=trace` when a custom `=destroy` that deallocates manually allocated resources is also used, and then only when there is a chance of cyclic references from items within the manually allocated resources when it is desired that `--gc:orc` be able to break and collect these cyclic referenced resources.  Currently however, there is a mutual use problem in that whichever of `=destroy`/`=trace` is used first will automatically create a version of the other which will then conflict with the creation of the second of the pair.  The work around for this problem is to forward declare the second of the "hooks" to prevent the automatic creation.
+
+The general pattern in using `=destroy` with `=trace` looks like:
 
 .. code-block:: nim
 
-  proc `=trace`(dest: var T; env: pointer) =
-    for child in childrenThatCanContainPointers(dest):
-      `=trace`(child, env)
+  type
+    Test[T] = object
+      size: Natural
+      arr: ptr UncheckedArray[T] # raw pointer field
+
+  proc makeTest[T](size: Natural): Test[T] = # custom allocation...
+    Test[T](size: size, arr: cast[ptr UncheckedArray[T]](alloc0(sizeof(T) * size)))
+
+
+  proc `=destroy`[T](dest: var Test[T]) =
+    if dest.arr != nil:
+      for i in 0 ..< dest.size: dest.arr[i].`=destroy`
+      dest.arr.dealloc
+
+  proc `=trace`[T](dest: var Test[T]; env: pointer) =
+    if dest.arr != nil: # trace the `T`'s which may be cyclic
+      for i in 0 ..< dest.size: dest.arr[i].`=trace` env
 
+  # following may be other custom "hooks" as required...
 
-**Note**: The `=trace` hooks is currently more experimental and less refined
+**Note**: The `=trace` hooks (which are only used by `--gc:orc`) are currently more experimental and less refined
 than the other hooks.