use std::cell::Cell;
use std::fmt::Debug;
use std::pin::Pin;
use crate::gc::Gc;
use crate::trace::Trace;
pub(crate) trait EntryLike: Debug {
fn is_root(&self) -> bool;
fn unmark_reachable(&self) -> bool;
}
impl<T> EntryLike for HeapEntry<T> where T: Trace {
fn is_root(&self) -> bool {
self.is_root.get()
}
fn unmark_reachable(&self) -> bool {
self.is_reachable.replace(false)
}
}
#[derive(Debug)]
pub(crate) struct HeapEntry<T> {
object: T,
is_reachable: Cell<bool>,
is_root: Cell<bool>,
}
impl<T: Trace> HeapEntry<T> {
pub fn new(object: T) -> Self {
Self {
object,
is_reachable: Cell::new(false),
is_root: Cell::new(false),
}
}
pub fn pin(object: T) -> Pin<Box<Self>> {
Box::pin(Self::new(object))
}
pub fn mark_reachable(&self) -> bool {
if self.is_reachable.replace(true) {
return false;
}
self.object.mark_children();
true
}
pub fn mark_root(&self) -> bool {
self.is_root.replace(true)
}
pub fn unmark_root(&self) -> bool {
self.is_root.replace(false)
}
#[inline(always)]
pub fn get(&self) -> &T {
&self.object
}
#[inline(always)]
pub fn get_gc(self: Pin<&Self>) -> Gc<T> {
let ptr = self.get_ref() as *const _;
unsafe { Gc::new(ptr) }
}
}