use crate::GarbageCollector;
use crate::collector::Trace;
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub(crate) struct SafePtr(pub(crate) usize);
unsafe impl Send for SafePtr {}
unsafe impl Sync for SafePtr {}
impl SafePtr {
pub(crate) fn from_ptr<T>(ptr: *const T) -> Self {
Self(ptr as usize)
}
pub(crate) fn as_ptr<T>(self) -> *const T {
self.0 as *const T
}
}
#[derive(Clone, Debug)]
pub(crate) struct TracePtr {
pub(crate) ptr: *const (),
pub(crate) trace_fn: fn(*const (), &GarbageCollector),
}
unsafe impl Send for TracePtr {}
unsafe impl Sync for TracePtr {}
impl TracePtr {
pub(crate) fn new<T: Trace>(obj: &T) -> Self {
fn trace_impl<T: Trace>(ptr: *const (), collector: &GarbageCollector) {
if ptr.is_null() {
return;
}
let ptr_addr = ptr as usize;
if ptr_addr < 4096 {
return;
}
unsafe {
let object = &*ptr.cast::<T>();
object.trace(collector);
}
}
Self {
ptr: std::ptr::from_ref::<T>(obj).cast::<()>(),
trace_fn: trace_impl::<T>,
}
}
pub(crate) fn new_from_ptr<T: Trace>(gc_ptr: *const T) -> Self {
fn trace_impl<T: Trace>(ptr: *const (), collector: &GarbageCollector) {
if ptr.is_null() {
return;
}
let ptr_addr = ptr as usize;
if ptr_addr < 4096 {
return;
}
unsafe {
let object = &*ptr.cast::<T>();
object.trace(collector);
}
}
Self {
ptr: gc_ptr.cast::<()>(),
trace_fn: trace_impl::<T>,
}
}
pub(crate) fn as_raw_ptr(&self) -> *const () {
self.ptr
}
pub(crate) unsafe fn trace(&self, collector: &GarbageCollector) {
(self.trace_fn)(self.ptr, collector);
}
}