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.
Implementations§
Trait Implementations§
source§impl<T> PartialEq<Gc<T>> for Root<T>where
T: Trace,
impl<T> PartialEq<Gc<T>> for Root<T>where
T: Trace,
source§impl<T> PartialEq<Root<T>> for Gc<T>where
T: Trace,
impl<T> PartialEq<Root<T>> for Gc<T>where
T: Trace,
source§impl<T> PartialEq for Gc<T>
impl<T> PartialEq for Gc<T>
impl<T> Copy for Gc<T>
impl<T> Eq for Gc<T>
Auto Trait Implementations§
impl<T> Freeze for Gc<T>
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Copy,
impl<T> CloneToUninit for Twhere
T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)