bsr 0.11.0

Tracing garbage collector for Amsel
Documentation
//! Contains the user-facing garbage collector API in the form of the `Gc` type.

use std::fmt::{Debug, Formatter};
use std::ops::Deref;

use crate::heap_entry::{EntryLike, HeapEntry};
use crate::trace::Trace;

/// A garbage-collected pointer to a value of type `T`.
pub struct Gc<T> {
    entry: *const HeapEntry<T>,
}

/// Implemented explicitly because deriving would require `T: Clone`.
impl<T> Clone for Gc<T> {
    fn clone(&self) -> Self {
        *self
    }
}

/// Implemented explicitly because deriving would require `T: Copy`.
impl<T> Copy for Gc<T> {}

impl<T> Gc<T> {
    /// Create a new `Gc` from a raw pointer to a heap entry.
    /// # Safety
    /// The pointer must be valid and point to a pinned entry.
    pub(super) unsafe fn new(entry: *const HeapEntry<T>) -> Self {
        Self { entry }
    }

    /// Get the entry for this `Gc`.
    pub(super) fn entry(&self) -> &HeapEntry<T> {
        // Safety: [entry] can only be called on reachable [Gc]s.
        // Implementors of [Trace] must ensure that all reachable objects are marked.
        unsafe { &*self.entry }
    }

    /// Is the object in the root set?
    pub fn is_root(&self) -> bool where T: Trace {
        self.entry().is_root()
    }
}


impl<T: Trace> Deref for Gc<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        // Safety: [deref] can only be called on reachable [Gc]s.
        // Implementors of [Trace] must ensure that all reachable objects are marked.
        unsafe { (*self.entry).get() }
    }
}

impl<T> Debug for Gc<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Gc")
            .field("entry", &self.entry)
            .finish()
    }
}

unsafe impl<T: Trace> Trace for Gc<T> {
    fn mark_children(&self) {
        self.entry().mark_reachable();
    }
}