pub extern crate bacon_rajan_cc;
use bacon_rajan_cc::{
Cc,
Trace,
number_of_roots_buffered,
collect_cycles,
};
const CC_MAX_ROOTS: usize = 128;
#[inline( always )]
pub fn cc<T: Trace>( value: T ) -> Cc<T> {
if number_of_roots_buffered() >= CC_MAX_ROOTS {
collect_cycles();
}
Cc::new( value )
}
#[cfg( test )]
mod tests {
use std::cell::RefCell;
use super::{
CC_MAX_ROOTS,
Trace,
Cc,
cc,
bacon_rajan_cc::{
Tracer,
number_of_roots_buffered,
collect_cycles
},
};
fn create_cycle() {
struct List( Vec<Cc<RefCell<List>>> );
impl Trace for List {
fn trace( &self, tracer: &mut Tracer ) {
self.0.trace( tracer );
}
}
{
let a = cc( RefCell::new( List( Vec::new() ) ) );
let b = cc( RefCell::new( List( Vec::new() ) ) );
{
let mut a = a.borrow_mut();
a.0.push( b.clone() );
}
{
let mut b = b.borrow_mut();
b.0.push( a.clone() );
}
}
}
#[test]
fn auto_collection() {
assert_eq!( number_of_roots_buffered(), 0, "start" );
for _ in 0 .. CC_MAX_ROOTS / 2 {
create_cycle();
}
assert_eq!( number_of_roots_buffered(), CC_MAX_ROOTS, "before collection" );
create_cycle();
assert_eq!( number_of_roots_buffered(), 2, "after collection" );
collect_cycles();
assert_eq!( number_of_roots_buffered(), 0, "finished" );
}
}