use crate::gc_box::{GcBox, GcHeader};
use crate::{Trace, Tracer};
use std::ops::Deref;
use std::ptr::NonNull;
#[repr(transparent)]
pub struct GcPtr<T: ?Sized>(NonNull<GcBox<T>>);
impl<T: ?Sized> GcPtr<T> {
#[inline]
#[allow(dead_code)]
pub(crate) fn new(ptr: NonNull<GcBox<T>>) -> Self {
Self(ptr)
}
#[inline]
pub unsafe fn root(self) -> GcRoot<T> {
unsafe {
self.0.as_ref().header.inc_root();
GcRoot(self)
}
}
#[inline]
pub fn as_ptr(&self) -> *const T {
unsafe { &self.0.as_ref().data as *const T }
}
#[inline]
pub(crate) fn header_ptr(&self) -> *const GcHeader {
unsafe { &self.0.as_ref().header as *const GcHeader }
}
}
impl<T: ?Sized> Copy for GcPtr<T> {}
impl<T: ?Sized> Clone for GcPtr<T> {
fn clone(&self) -> Self {
*self
}
}
unsafe impl<T: Send> Send for GcPtr<T> {}
unsafe impl<T: Sync> Sync for GcPtr<T> {}
#[repr(transparent)]
pub struct GcRoot<T: ?Sized>(GcPtr<T>);
impl<T: ?Sized> GcRoot<T> {
#[inline]
pub(crate) unsafe fn new_from_nonnull(ptr: NonNull<GcBox<T>>) -> Self {
Self(GcPtr(ptr))
}
#[inline]
pub fn as_ptr(&self) -> GcPtr<T> {
self.0
}
}
impl<T: ?Sized> Deref for GcRoot<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &self.0.0.as_ref().data }
}
}
impl<T: ?Sized> Clone for GcRoot<T> {
#[inline]
fn clone(&self) -> Self {
unsafe {
self.0.0.as_ref().header.inc_root();
}
Self(self.0)
}
}
impl<T: ?Sized> Drop for GcRoot<T> {
fn drop(&mut self) {
unsafe {
self.0.0.as_ref().header.dec_root();
}
}
}
unsafe impl<T: Send> Send for GcRoot<T> {}
unsafe impl<T: Sync> Sync for GcRoot<T> {}
unsafe impl<T: Trace> Trace for GcPtr<T> {
fn trace(&self, tracer: &Tracer) {
tracer.mark(self);
}
}