From 5d63639e46df447540c7ac52d6d2ef99ff941a3a Mon Sep 17 00:00:00 2001 From: fren_gor Date: Tue, 6 Aug 2024 06:16:29 +0200 Subject: [PATCH] Update CONTRIBUTING.md --- CONTRIBUTING.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ec4f4a..f782443 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ Also, remember to open the pull requests toward the `dev` branch. The `main` bra The core idea behind the algorithm is the same as the one presented by Lins in ["Cyclic Reference Counting With Lazy Mark-Scan"](https://kar.kent.ac.uk/22347/1/CyclicLin.pdf) and by Bacon and Rajan in ["Concurrent Cycle Collection in Reference Counted Systems"](https://pages.cs.wisc.edu/~cymen/misc/interests/Bacon01Concurrent.pdf). -However, the implementation differs in order to make the collector faster and more resilient to random panics and failures in general. +However, the implementation differs in order to make the collector faster and more resilient to panics and failures. > [!IMPORTANT] > `rust-cc` is *not* strictly an implementation of the algorithm shown in the linked papers and it's never been @@ -23,24 +23,33 @@ The `POSSIBLE_CYCLES` is an (intrusive) list which contains the possible roots o Sometimes (see [`crate::trigger_collection`](./src/lib.rs)), when creating a new `Cc` or when `collect_cycles` is called, the objects inside the `POSSIBLE_CYCLES` list are checked to see if they are part of a garbage cycle. -Therefore, they undergo two tracing passes: -- **Trace Counting:** during this phase, starting from the elements inside `POSSIBLE_CYCLES`, - objects are traced to count the amount of pointers to each `CcBox` that is reachable from the list's `Cc`s. +Therefore, they undergo two tracing phases: +- **Trace Counting:** during this phase, a breadth-first traversal of the heap is performed starting from the elements inside + `POSSIBLE_CYCLES` to count the number of pointers to each `CcBox` that is reachable from the list's `Cc`s. The `tracing_counter` "field" (see the [`counter_marker` module](./src/counter_marker.rs) for more info) is used to keep track of this number.
About tracing_counter

In the papers, Lins, Bacon and Rajan decrement the RC itself instead of using another counter. However, if during tracing there was a panic, it would be hard for `rust-cc` to restore the RC correctly. This is the reason for the choice of having another counter. - The invariant regarding this second counter is that it must always be between 0 and RC inclusively. + The invariant regarding this second counter is that it must always be between 0 and RC (inclusively).

- **Trace Roots:** now, every `CcBox` which has the RC strictly greater than `tracing_counter` can be considered a root, - since it must exist a `Cc` pointer which points at it that hasn't been traced before. Thus, a trace is started from these roots, - and all objects not reached during this trace are finalized/deallocated (the story is more complicated because of possible + since it must exist a `Cc` pointer which points at it that hasn't been traced in the previous phase. Thus, a trace is started from these roots, + and all objects not reached during this trace are finalized/deallocated (this is actually more complex due to possible object resurrections, see the comments in [lib.rs](./src/lib.rs)). Note that this second phase is correct only if the graph formed by the pointers is not changed between the two phases. Thus, this is a key requirement of the `Trace` trait and one of the reasons it is marked `unsafe`. +## Using lists and queues + +When debug assertions are enabled, the `add` method may panic before actually updating the list to contain the added object. +Similarly, the `remove` method may panic after having removed the object from the list. + +Thus, marking should be done only: + - after the call to the `add` method + - before the call to the `remove` method. + ## Writing tests Every unit test should start with a call to `tests::reset_state()` to make sure errors in other tests don't impact the current one.