use core::cell::Cell;
use crate::{GcSafe, Trace, GcVisitor, NullTrace, TraceImmutable, GcDirectBarrier,};
#[derive(Default, Clone, Debug)]
#[repr(transparent)]
pub struct GcCell<T: Trace + Copy>(Cell<T>);
impl<T: Trace + Copy> GcCell<T> {
#[inline]
pub fn new(value: T) -> Self {
GcCell(Cell::new(value))
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
self.0.get_mut()
}
#[inline]
pub fn as_ptr(&self) -> *mut T {
self.0.as_ptr()
}
#[inline]
pub fn get(&self) -> T {
self.0.get()
}
}
impl<T: NullTrace + Copy> GcCell<T> {
#[inline]
pub fn set(&self, value: T) {
self.0.set(value)
}
}
unsafe impl<'gc, OwningRef, Value> GcDirectBarrier<'gc, OwningRef> for GcCell<Value>
where Value: GcDirectBarrier<'gc, OwningRef> + Copy {
#[inline]
unsafe fn write_barrier(
&self, owner: &OwningRef,
field_offset: usize
) {
self.get().write_barrier(owner, field_offset)
}
}
unsafe impl<T: Trace + Copy> Trace for GcCell<T> {
const NEEDS_TRACE: bool = T::NEEDS_TRACE;
#[inline]
fn visit<V: GcVisitor>(&mut self, visitor: &mut V) -> Result<(), V::Err> {
visitor.visit(self.get_mut())
}
}
unsafe impl<T: GcSafe + NullTrace + Copy> TraceImmutable for GcCell<T> {
#[inline]
fn visit_immutable<V: GcVisitor>(&self, visitor: &mut V) -> Result<(), <V as GcVisitor>::Err> {
let mut value = self.get();
visitor.visit(&mut value)?;
self.set(value);
Ok(())
}
}
unsafe impl<T: GcSafe + Copy + NullTrace> NullTrace for GcCell<T> {}
unsafe impl<T: GcSafe + Copy> GcSafe for GcCell<T> {
const NEEDS_DROP: bool = false;
}