1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
use core::fmt;
use core::cell::{Cell, RefCell};
/// Trait required for all GC'd data.
/// Unsafe because if the `trace()` implementation fails to call `Gc::mark_trace()`
/// and `GcWeak::mark_trace()` on all of the `Gc` and `GcWeak` pointers that it can reach,
/// the GC will free memory that is still in use.
/// SAFETY: If the receiver also impls `Drop`, the `drop()` impl must not deref any `Gc` or `GcWeak` pointers
pub unsafe trait GcTrace: fmt::Debug {
/// SAFETY: Must call `Gc::mark_trace()` on every reachable Gc handle
fn trace(&self);
/// If the GcTrace owns any allocations, this should return the extra allocated size.
/// If the allocation can change size, like a Vec<T>, then don't include it in the
/// size hint, or return a const estimate of the average size.
#[inline]
fn size_hint(&self) -> usize { 0 }
fn cleanup(&self) { }
}
// Arrays
unsafe impl<T> GcTrace for [T] where T: GcTrace {
fn trace(&self) {
for item in self.iter() {
item.trace()
}
}
fn size_hint(&self) -> usize {
self.iter().map(GcTrace::size_hint).sum()
}
}
// Cells
unsafe impl<T> GcTrace for Cell<T> where T: GcTrace + Copy {
fn trace(&self) {
self.get().trace()
}
fn size_hint(&self) -> usize {
self.get().size_hint()
}
}
unsafe impl<T> GcTrace for RefCell<T> where T: GcTrace {
fn trace(&self) {
self.borrow().trace()
}
fn size_hint(&self) -> usize {
self.borrow().size_hint()
}
}