ghost_gc/
gc.rs

1use core::ops::Deref;
2use std::{fmt::Debug, hash::Hash};
3
4use crate::{
5    context::Mutation, gc_box::GcBox, locked::Unlock, Collect, Invariant, UniqueGc, Weak, Write,
6};
7
8/// A thin, copyable, garbage collected pointer type.
9pub struct Gc<'b, T: ?Sized>(GcBox<T>, Invariant<'b>);
10
11impl<'b, T: Collect> Gc<'b, T> {
12    /// Allocates garbage collected memory on the heap and then places `val`
13    /// into it.
14    ///
15    /// This allocates regardless of if `T` is zero-sized.
16    ///
17    /// If initialization of a more complex type is required, see [`UniqueGc`].
18    pub fn new(val: T, mt: &Mutation<'b>) -> Gc<'b, T> {
19        let this = UniqueGc::new(val, mt);
20        UniqueGc::into_gc(this)
21    }
22}
23
24impl<'b> Gc<'b, str> {
25    pub fn from_str(s: &str, mt: &Mutation<'b>) -> Gc<'b, str> {
26        UniqueGc::into_gc(UniqueGc::from_str(s, mt))
27    }
28}
29
30impl<'b, T: ?Sized> Gc<'b, T> {
31    pub fn write(&self) -> &Write<T> {
32        unsafe { Write::new_unchecked(self) }
33    }
34
35    pub fn unlock(&self) -> &T::Unlocked
36    where
37        T: Unlock,
38    {
39        self.write().unlock()
40    }
41
42    pub fn as_ptr(&self) -> *mut T {
43        self.0.data_ptr()
44    }
45
46    /// Returns a reference to the contained value, which lasts for as long as
47    /// the current view is active.
48    pub fn long_ref(&self) -> &'b T {
49        unsafe { &*self.as_ptr() }
50    }
51
52    pub fn downgrade(this: Gc<'b, T>) -> Weak<'b, T> {
53        unsafe { Weak::from_box(this.0) }
54    }
55
56    // pub(crate) fn into_box(self) -> GcBox<T> {
57    //     self.0
58    // }
59
60    pub(crate) unsafe fn from_box(ptr: GcBox<T>) -> Gc<'b, T> {
61        Gc(ptr, Invariant)
62    }
63}
64
65impl<T: ?Sized> Deref for Gc<'_, T> {
66    type Target = T;
67
68    fn deref(&self) -> &Self::Target {
69        unsafe { self.0.data() }
70    }
71}
72
73unsafe impl<T: ?Sized> Collect for Gc<'_, T> {
74    const NEEDS_TRACE: bool = true;
75
76    fn trace(&self, c: &crate::Collector) {
77        use crate::gc_box::Colour;
78
79        match self.0.colour() {
80            Colour::Gray | Colour::White | Colour::Weak => {
81                unsafe { self.0.set_colour(Colour::Gray) };
82
83                c.context().push_box(self.0.erase());
84            }
85            Colour::Black => {}
86        }
87    }
88}
89
90impl<T: ?Sized> Clone for Gc<'_, T> {
91    fn clone(&self) -> Self {
92        *self
93    }
94}
95
96impl<T: ?Sized> Copy for Gc<'_, T> {}
97
98impl<T: Debug + ?Sized> Debug for Gc<'_, T> {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        (**self).fmt(f)
101    }
102}
103
104impl<T: ?Sized + PartialEq> PartialEq for Gc<'_, T> {
105    fn eq(&self, other: &Self) -> bool {
106        **self == **other
107    }
108}
109
110impl<T: ?Sized + Eq> Eq for Gc<'_, T> {}
111
112impl<T: ?Sized + PartialOrd> PartialOrd for Gc<'_, T> {
113    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
114        (**self).partial_cmp(other)
115    }
116}
117
118impl<T: ?Sized + Ord> Ord for Gc<'_, T> {
119    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
120        (**self).cmp(other)
121    }
122}
123
124impl<T: ?Sized + Hash> Hash for Gc<'_, T> {
125    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
126        (**self).hash(state);
127    }
128}