Function bacon_rajan_cc::collect::collect_cycles
[−]
[src]
pub fn collect_cycles()
Invoke cycle collection for all Cc<T>
s on this thread.
You may wish to do this when the roots buffer reaches a certain size, when
memory is low, or at opportune moments within your application (such as when
the user has been inactive for n
seconds in a GUI application).
This happens in three phases:
mark_roots
: We mark the roots and decrement reference counts as we go. This is optimistically removing the strong references held by the potentially dead cycles.scan_roots
: Then we perform a second traversal which marks the garbage nodes with a reference count of 0 as White and the non-garbage nodes with a reference count > 0 as Black. The latter group's reference count is restored to its previous value from before step (1).collect_roots
: Finally, the buffer of possible dead cycle roots is emptied and members of dead cycles (White nodes) are dropped.
use bacon_rajan_cc::{Cc, Trace, Tracer, collect_cycles}; use std::cell::RefCell; // The number of Gadgets allocated at any given time. thread_local!(static GADGET_COUNT: RefCell<usize> = RefCell::new(0)); struct Gadget { parent: Option<Cc<RefCell<Gadget>>>, children: Vec<Cc<RefCell<Gadget>>>, // ... } impl Gadget { fn new() -> Gadget { GADGET_COUNT.with(|c| *c.borrow_mut() += 1); Gadget { parent: None, children: vec!() } } } impl Trace for Gadget { fn trace(&mut self, tracer: &mut Tracer) { if let Some(ref mut p) = self.parent { tracer(p); } for child in &mut self.children { tracer(child); } } } impl Drop for Gadget { fn drop(&mut self) { GADGET_COUNT.with(|c| *c.borrow_mut() -= 1); } } fn add_child(parent: &mut Cc<RefCell<Gadget>>) -> Cc<RefCell<Gadget>> { let child = Cc::new(RefCell::new(Gadget::new())); child.borrow_mut().parent = Some(parent.clone()); parent.borrow_mut().children.push(child.clone()); child } pub fn main() { // Initially, no gadgets. GADGET_COUNT.with(|c| assert_eq!(*c.borrow(), 0)); { // Create cycles. let mut parent = Cc::new(RefCell::new(Gadget::new())); for _ in 0..10 { add_child(&mut parent); } // We created 1 parent and 10 child gadgets. GADGET_COUNT.with(|c| assert_eq!(*c.borrow(), 11)); } // The members of the cycle are now dead, but because of the cycles // could not be eagerly collected. GADGET_COUNT.with(|c| assert_eq!(*c.borrow(), 11)); // After calling `collect_cycles`, the cycles are detected and the // members of the dead cycles are dropped. collect_cycles(); GADGET_COUNT.with(|c| assert_eq!(*c.borrow(), 0)); }