bsr 0.10.0

A minimal garbage collection library written in safe Rust
Documentation
bsr-0.10.0 has been yanked.

BSR - Simple Garbage Collection for Rust

Example:

use bsr::{GC, Managed, Shared, Tracer};
struct List {
value: i32,
next: Option<Shared<List>>,
}

impl List {
pub fn new(value: i32) -> Self {
Self { value, next: None }
}

pub fn cons(&mut self, next: Shared<List>) {
self.next = Some(next)
}
}

impl Managed for List {
fn trace<T>(&self, tracer: &mut T) where T: Tracer {
if let Some(next) = self.next.as_ref() {
tracer.mark(&next)        
}
}

fn dissolve(&mut self) {
self.next = None;
}
}

fn test_gc() {
let mut gc = GC::default();
let head = gc.make(List::new(10));
let second = gc.make(List::new(20));
head.borrow_mut().cons(second);

let unreachable = gc.make(List::new(30));
drop(unreachable);

gc.unmark_all();
gc.mark(&head);
gc.sweep(); // == 1, the unreachable list
}

Behind the scenes

bsr uses reference counting ([std::rc::Rc]) and cycle elimination to provide a simple to use garbage collector written entirely in safe Rust. Creating a new managed object with [GC::make] returns a [Shared] which may then be passed around the application, copied, and dropped. As with [std::rc::Rc], when the last [Shared] to a managed object is dropped, the object also gets dropped. To allow for reference cycles, a tracing mechanism using [Trace] is implemented. Managed objects must inform the garbage collector of all [Shared] to other managed objects they hold. Failure to do so will most likely result in a crash, as the garbage collector will try to dissolve objects it considers unreachable. Similarly, failing to mark a root object (an object which is not reachable from any other object but is required to stay alive) before calling [GC::sweep] will clobber objects and then crash.

To break up reference cycles, managed objects may be asked to destroy any references to other objects using the [Dissolve] trait. An [Option<Shared<T>>] is one way to achieve this. Only objects the garbage collector considers unreachable (not marked as root and not reachable through calling [Trace::trace] on a root or its children) will ever be dissolved.