Skip to content

Commit

Permalink
Update CONTRIBUTING.md
Browse files Browse the repository at this point in the history
  • Loading branch information
frengor committed Aug 6, 2024
1 parent 53e803c commit 5d63639
Showing 1 changed file with 16 additions and 7 deletions.
23 changes: 16 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
<details>
<summary>About tracing_counter</summary>
<p>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).
</p>
</details>
- **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.
Expand Down

0 comments on commit 5d63639

Please sign in to comment.