gc_api 0.5.0

Generic abstractions for a multithreaded garbage collector
Documentation
use crate::trace::roots::{GcRootStorage, RootStorage};
use crate::Alloc;
use crate::Gc;
use smallvec::{Array, SmallVec};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};

pub struct StackRoots<
    'r,
    R: RootStorage<A>,
    A,
    S: Array<Item = R::Index> = [<R as RootStorage<A>>::Index; 8],
> {
    storage: SmallVec<S>,
    root_source: &'r mut R,
    _phantom: PhantomData<A>,
}

impl<'r, R, A, S> From<&'r mut R> for StackRoots<'r, R, A, S>
    where
        R: RootStorage<A>,
        S: Array<Item = R::Index>,
{
    fn from(root_source: &'r mut R) -> Self {
        StackRoots {
            storage: SmallVec::new(),
            root_source,
            _phantom: PhantomData,
        }
    }
}

impl<'r, R, A, S> RootStorage<A> for StackRoots<'r, R, A, S>
where
    R: RootStorage<A>,
    S: Array<Item = R::Index>,
{
    type Index = R::Index;

    #[inline(always)]
    fn remove_root(&mut self, index: Self::Index) -> bool {
        self.root_source.remove_root(index)
    }
}

impl<'r, T, R, A, S> GcRootStorage<T, A> for StackRoots<'r, R, A, S>
where
    A: Alloc<T>,
    R: RootStorage<A> + GcRootStorage<T, A>,
    S: Array<Item = R::Index>,
{
    #[inline(always)]
    fn add_root(&mut self, root: &Gc<T, A>) -> Self::Index {
        self.root_source.add_root(root)
    }
}

impl<'r, R, S, A> Drop for StackRoots<'r, R, A, S>
where
    S: Array<Item = R::Index>,
    R: RootStorage<A>,
{
    fn drop(&mut self) {
        while let Some(root) = self.storage.pop() {
            self.root_source.remove_root(root);
        }
    }
}

impl<'r, R: RootStorage<A>, A, S: Array<Item = R::Index>> Deref for StackRoots<'r, R, A, S> {
    type Target = R;

    fn deref(&self) -> &Self::Target {
        self.root_source
    }
}

impl<'r, R: RootStorage<A>, A, S: Array<Item = R::Index>> DerefMut for StackRoots<'r, R, A, S> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.root_source
    }
}

#[cfg(feature = "slab")]
use crate::trace::{roots::UntypedTracable, Trace, TracingAllocator};

#[cfg(feature = "slab")]
pub type UniformHandleRoots<A, R> = slab::Slab<UntypedTracable<A, R>>;

#[cfg(feature = "slab")]
impl<A: TracingAllocator, R> RootStorage<A> for UniformHandleRoots<A, R> {
    type Index = usize;

    #[inline(always)]
    fn remove_root(&mut self, index: Self::Index) -> bool {
        self.try_remove(index).is_some()
    }
}

#[cfg(feature = "slab")]
impl<T, A, R> GcRootStorage<T, A> for UniformHandleRoots<A, R>
where
    T: Trace<A>,
    A: Alloc<T, RawHandle = R> + TracingAllocator,
    R: Clone,
{
    #[inline(always)]
    fn add_root(&mut self, root: &Gc<T, A>) -> Self::Index {
        self.insert(UntypedTracable::from_handle(root.clone()))
    }
}