use crate::{
gc::{GcPtr, GcRuntime, HasIndirectionPtr, TypeTrace},
TypeMemory,
};
use std::marker::PhantomData;
use std::sync::{Arc, Weak};
pub struct GcRootPtr<T: TypeMemory + TypeTrace, G: GcRuntime<T>> {
handle: GcPtr,
runtime: Weak<G>,
ty: PhantomData<T>,
}
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> Clone for GcRootPtr<T, G> {
fn clone(&self) -> Self {
if let Some(runtime) = self.runtime.upgrade() {
runtime.root(self.handle)
}
Self {
handle: self.handle,
runtime: self.runtime.clone(),
ty: PhantomData,
}
}
}
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> GcRootPtr<T, G> {
pub fn new(runtime: &Arc<G>, handle: GcPtr) -> Self {
runtime.root(handle);
Self {
handle,
runtime: Arc::downgrade(runtime),
ty: PhantomData,
}
}
pub fn handle(&self) -> GcPtr {
self.handle
}
pub fn unroot(self) -> GcPtr {
self.handle
}
}
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> Into<GcPtr> for GcRootPtr<T, G> {
fn into(self) -> GcPtr {
self.handle
}
}
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> Drop for GcRootPtr<T, G> {
fn drop(&mut self) {
if let Some(runtime) = self.runtime.upgrade() {
runtime.unroot(self.handle)
}
}
}
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> HasIndirectionPtr for GcRootPtr<T, G> {
unsafe fn deref<R: Sized>(&self) -> *const R {
self.handle.deref()
}
}