[][src]Crate gcmodule

Reference cycle garbage collection inspired by cpython.

The type Cc<T> provides shared ownership of a value of type T, similar to std::rc::Rc<T>. Unlike Rc<T>, collect_thread_cycles can be used to drop unreachable values that form circular references.

Cloning references

Similar to Rc<T>, use clone() to get cloned references.

use gcmodule::Cc;
let foo = Cc::new(vec![1, 2, 3]);
let foo_cloned = foo.clone();
// foo and foo_cloned both point to the same `vec![1, 2, 3]`.
assert!(std::ptr::eq(&foo[0], &foo_cloned[0]));

Collecting cycles

Use collect_thread_cycles() to collect thread-local garbage.

use gcmodule::{Cc, Trace};
use std::cell::RefCell;
{
    type List = Cc<RefCell<Vec<Box<dyn Trace>>>>;
    let a: List = Default::default();
    let b: List = Default::default();
    a.borrow_mut().push(Box::new(b.clone()));
    b.borrow_mut().push(Box::new(a.clone()));
}

// a and b form circular references. The objects they point to are not
// dropped automatically, despite both variables run out of scope.

gcmodule::collect_thread_cycles();  // This will drop a and b.

Definiting new types

Cc<T> requires Trace implemented for T so the collector knows how values are referred.

Acyclic types

Types that do not store references to other objects, or only store references to atomic types (such as numbers or strings), can opt-out cyclic garbage collection for performance. This can be done by using the untrack! macro:

use gcmodule::{untrack, Cc};
struct Foo(String);
struct Bar;
untrack!(Foo, Bar); // Opt-out cycle collector. Ref-count still works.

let foo = Cc::new(Foo("abc".to_string()));
let bar = Cc::new(Bar);
let foo_cloned = foo.clone(); // Share the same `"abc"` with `foo`.
drop(foo); // The ref count of `"abc"` drops from 2 to 1.
drop(foo_cloned); // `"abc"` will be dropped here..

Container types

Types that store references to other objects, need to implement the Trace trait. For example:

use gcmodule::{Cc, Trace, Tracer};
struct Foo<T1, T2>(T1, T2, u8);

impl<T1: Trace, T2: Trace> Trace for Foo<T1, T2> {
    fn trace(&self, tracer: &mut Tracer) {
        self.0.trace(tracer);
        self.1.trace(tracer);
    }
}

let foo = Cc::new(Foo(Foo(Cc::new(1), 2, 3), Cc::new("abc"), 10));

Macros

untrack

Mark types as "untracked". Untracked types opt-out the cycle collector.

Structs

Cc

A single-threaded reference-counting pointer that integrates with cyclic garbage collection.

Traits

Trace

Defines how the cycle collector should collect a type.

Functions

collect_thread_cycles

Collect cyclic garbage in the current thread. Return the number of objects collected.

Type Definitions

Tracer

Callback function that serves as the parameter of Trace::trace.