tracing-rc 0.1.3

Cycle-aware reference-counted pointers with a safe, simple api
Documentation

Cycle collecting reference counted pointers for Rust with a safe api.

This crate is most useful when you have a data structure with inter-dependent nodes of arbitrary lifetimes and no clear parent-children relationships.

If you can be certain that the layout of your data will be acyclic, or [std::rc::Weak] would be sufficient to prevent leaks, this type is probably not a good fit. If you know all of your data will be dropped after a certain phase of your program completes, you will probably prefer arena allocation through a crate like typed-arena, generational-arena, etc.

Concurrent Collection

Experimental support for concurrent collection may be enabled with the sync feature flag. When enabled, a sync::Agc type will be provided, paralleling std::sync::Arc. Note that you will need to call sync::collect instead of rc::collect to collect garbage generated by Agc values.

Basic Example

# use tracing_rc::rc::{
#     collect_full,
#     Gc,
#     GcVisitor,
#     Trace,
# };
#
struct GraphNode<T: 'static> {
    data: T,
    edge: Option<Gc<GraphNode<T>>>,
}

impl<T> Trace for GraphNode<T> {
    fn visit_children(&self, visitor: &mut GcVisitor) {
        self.edge.visit_children(visitor);
    }
}

# fn main() {
{
    let node_a = Gc::new(GraphNode {
        data: 10,
        edge: None,
    });
    let node_b = Gc::new(GraphNode {
        data: 11,
        edge: None,
    });
    let node_c = Gc::new(GraphNode {
        data: 12,
        edge: Some(node_a.clone()),
    });

    node_a.borrow_mut().edge = Some(node_b.clone());
    node_b.borrow_mut().edge = Some(node_c);

    let a = node_a.borrow();
    let b = a.edge.as_ref().unwrap().borrow();
    let c = b.edge.as_ref().unwrap().borrow();

    assert_eq!(a.data, c.edge.as_ref().unwrap().borrow().data);
    // all of the nodes go out of scope at this point and would normally be leaked.
}

// In this simple example, we always have cycles and our program is complete after this,
// so we can't take advantage of the young generation picking up acyclic pointers without
// tracing.
collect_full();

// All leaked nodes have been cleaned up!
# }