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>
This commit is contained in:
GordonBGood
2021-07-15 19:35:53 +07:00
committed by GitHub
parent a6ff6e7871
commit 8c6dd2b9a9

View File

@@ -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)))
**Note**: The `=trace` hooks is currently more experimental and less refined
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 (which are only used by `--gc:orc`) are currently more experimental and less refined
than the other hooks.