use gc_lang::{Gc, Heap, Trace, Tracer};
struct Node {
name: &'static str,
children: Vec<Gc<Node>>,
}
impl Trace for Node {
fn trace(&self, tracer: &mut Tracer<'_>) {
for &child in &self.children {
tracer.mark(child);
}
}
}
fn main() {
let mut heap = Heap::new();
let shared = heap.alloc(Node {
name: "shared",
children: vec![],
});
let c = heap.alloc(Node {
name: "c",
children: vec![],
});
let a = heap.alloc(Node {
name: "a",
children: vec![shared],
});
let b = heap.alloc(Node {
name: "b",
children: vec![shared, c],
});
let root_x = heap.alloc(Node {
name: "root_x",
children: vec![a, b],
});
let root_y = heap.alloc(Node {
name: "root_y",
children: vec![b],
});
let names = |heap: &Heap<Node>, handles: &[Gc<Node>]| {
handles
.iter()
.filter_map(|&h| heap.get(h).map(|n| n.name))
.collect::<Vec<_>>()
.join(", ")
};
let everything = [shared, c, a, b, root_x, root_y];
println!("initial live objects: {}", heap.len());
let stats = heap.collect([root_x, root_y]);
println!(
"roots {{root_x, root_y}} -> freed {}, live: [{}]",
stats.freed,
names(&heap, &everything)
);
assert_eq!(stats.freed, 0);
let stats = heap.collect([root_y]);
println!(
"roots {{root_y}} -> freed {}, live: [{}]",
stats.freed,
names(&heap, &everything)
);
assert!(heap.get(a).is_none());
assert!(heap.get(shared).is_some());
assert!(heap.get(root_x).is_none());
let stats = heap.collect([]);
println!(
"roots {{}} -> freed {}, live: []",
stats.freed
);
assert!(heap.is_empty());
}