crftng-intrprtrs/gc/src/trace.rs

46 lines
1.0 KiB
Rust

use std::{collections::HashSet, ops::Deref};
use crate::gc_ref::GcRef;
pub struct GCTracer {
accessible: HashSet<*const ()>,
explored: HashSet<*const ()>,
}
impl GCTracer {
pub(super) fn with_capacity(cap: usize) -> Self {
Self {
accessible: HashSet::with_capacity(cap),
explored: HashSet::with_capacity(cap),
}
}
pub fn is_accessible(&self, ptr: *const ()) -> bool {
self.accessible.contains(&ptr)
}
pub fn mark_reachable_rec<T: GCTrace>(&mut self, obj: &T) {
let ptr = obj as *const T as *const ();
if self.explored.insert(ptr) {
obj.trace(self);
}
}
}
pub use gctrace_derive::GCTrace;
///
/// # Safety
/// Implementors of the trait *need* to ensure that every reachable reference gets marked as
/// reachable by callign trace on it
pub unsafe trait GCTrace {
fn trace(&self, _tracer: &mut GCTracer) {}
}
unsafe impl<T: GCTrace> GCTrace for GcRef<T> {
fn trace(&self, tracer: &mut GCTracer) {
tracer.accessible.insert(self.0.as_ptr() as *const ());
tracer.mark_reachable_rec(self.deref());
}
}