sphinx/runtime/gc/
trace.rs

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