Struct safe_gc::Gc

source ·
pub struct Gc<T> { /* private fields */ }
Expand description

A reference to a garbage-collected T.

Gc<T> should be used when:

  • Referencing other GC-managed objects from within a GC-managed object’s type definition.

  • Traversing or mutating GC-managed objects when you know a garbage collection cannot happen.

A Gc<T> does not root the referenced T or keep it alive across garbage collections. (The Root<T> type does that.) Therefore, Gc<T> should not be used to hold onto GC references across any operation that could trigger a garbage collection.

§Example: Referencing Other GC-Managed Objects Within a GC-Managed Object

use safe_gc::{Collector, Gc, Trace};

struct Tree<T: Trace> {
    // A non-nullable reference to a GC-managed `T`.
    value: Gc<T>,

    // Nullable references to parent, left, and right tree nodes.
    parent: Option<Gc<Tree<T>>>,
    left: Option<Gc<Tree<T>>>,
    right: Option<Gc<Tree<T>>>,
}

impl<T: Trace> Trace for Tree<T> {
    fn trace(&self, collector: &mut Collector) {
        // Report each of the `Gc<T>`s referenced from within `self` to the
        // collector. See the `Trace` docs for more details.
        collector.edge(self.value);
        if let Some(parent) = self.parent {
            collector.edge(parent);
        }
        if let Some(left) = self.left {
            collector.edge(left);
        }
        if let Some(right) = self.right {
            collector.edge(right);
        }
    }
}

§Example: Accessing a Gc<T>’s referenced T

use safe_gc::{Gc, Heap, Trace};

struct Node {
    value: u32,
    tail: Option<Gc<Node>>,
}

impl Trace for Node {
    // ...
}

let mut heap = Heap::new();

let a = heap.alloc(Node { value: 36, tail: None });
let b = heap.alloc(Node { value: 42, tail: Some(a.into()) });
let c = heap.alloc(Node { value: 99, tail: Some(b.clone().into()) });

// Read `(*c).tail`.
let c_tail = heap[&c].tail;
assert_eq!(c_tail, Some(b.into()));

// Write `(*c).tail = None`.
heap[&c].tail = None;

§Example: Downgrading a Root<T> into a Gc<T>

The Heap::alloc method returns rooted references, but to store those references into the field of a GC-managed object, you’ll need to unroot the reference with Root<T>::unrooted. (You can also use root.into() or Gc::from(root).)

use safe_gc::{Gc, Heap, Root, Trace};

struct Cat {
    siblings: Vec<Gc<Cat>>,
}

impl Trace for Cat {
    // ...
}

let mut heap = Heap::new();

let momo: Root<Cat> = heap.alloc(Cat { siblings: vec![] });
let juno: Root<Cat> = heap.alloc(Cat { siblings: vec![] });

// Add `momo` and `juno` to each other's siblings vectors. This requires
// downgrading the `Root<Cat>`s to `Gc<Cat>`s via the `unrooted` method.
heap[&momo].siblings.push(juno.unrooted());
heap[&juno].siblings.push(momo.unrooted());

§Example: Upgrading a Gc<T> into a Root<T>

You can upgrade a Gc<T> into a Root<T> via the Heap::root method, so that you can hold references to GC-objects across operations that can potentially trigger garbage collections.

See the docs for Heap::root for more details and an example.

Trait Implementations§

source§

impl<T> Clone for Gc<T>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T> Debug for Gc<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'a, T> From<&'a Root<T>> for Gc<T>
where T: Trace,

source§

fn from(root: &'a Root<T>) -> Self

Converts to this type from the input type.
source§

impl<T> From<Root<T>> for Gc<T>
where T: Trace,

source§

fn from(root: Root<T>) -> Self

Converts to this type from the input type.
source§

impl<T> Hash for Gc<T>

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<T> Index<Gc<T>> for Heap
where T: Trace,

§

type Output = T

The returned type after indexing.
source§

fn index(&self, index: Gc<T>) -> &Self::Output

Performs the indexing (container[index]) operation. Read more
source§

impl<T> IndexMut<Gc<T>> for Heap
where T: Trace,

source§

fn index_mut(&mut self, gc: Gc<T>) -> &mut Self::Output

Performs the mutable indexing (container[index]) operation. Read more
source§

impl<T> PartialEq<Gc<T>> for Root<T>
where T: Trace,

source§

fn eq(&self, other: &Gc<T>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T> PartialEq<Root<T>> for Gc<T>
where T: Trace,

source§

fn eq(&self, other: &Root<T>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T> PartialEq for Gc<T>

source§

fn eq(&self, other: &Self) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T> Copy for Gc<T>

source§

impl<T> Eq for Gc<T>

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for Gc<T>
where T: RefUnwindSafe,

§

impl<T> !Send for Gc<T>

§

impl<T> !Sync for Gc<T>

§

impl<T> Unpin for Gc<T>

§

impl<T> UnwindSafe for Gc<T>
where T: RefUnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.