ghost_gc/
locked.rs

1//! Shareable containers which can be made mutable when inside a [`Gc`].
2//!
3//! [`Gc`]: crate::Gc
4
5use std::cell::{Cell, OnceCell, RefCell};
6
7use crate::Collect;
8
9/// A marker for types which allow a [`Collect`] implementation on an
10/// interiorly mutable type.
11pub trait Unlock {
12    type Unlocked: ?Sized;
13
14    /// # Safety
15    /// The parent `Gc` must have been marked as unlocked.
16    unsafe fn unlock_unchecked(&self) -> &Self::Unlocked;
17}
18
19#[derive(Default)]
20#[repr(transparent)]
21pub struct LockedCell<T: ?Sized>(Cell<T>);
22
23impl<T> LockedCell<T> {
24    pub const fn new(value: T) -> LockedCell<T> {
25        LockedCell(Cell::new(value))
26    }
27
28    pub fn into_inner(self) -> T {
29        self.0.into_inner()
30    }
31}
32
33impl<T: Copy> LockedCell<T> {
34    pub fn get(&self) -> T {
35        self.0.get()
36    }
37
38    pub fn get_mut(&mut self) -> &mut T {
39        self.0.get_mut()
40    }
41}
42
43impl<T: ?Sized> LockedCell<T> {
44    pub const fn as_ptr(&self) -> *mut T {
45        self.0.as_ptr()
46    }
47}
48
49impl<T> Clone for LockedCell<T>
50where
51    T: Copy,
52{
53    fn clone(&self) -> Self {
54        Self(self.0.clone())
55    }
56}
57
58impl<T> std::fmt::Debug for LockedCell<T>
59where
60    T: std::fmt::Debug + Copy,
61{
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        f.debug_tuple("LockedCell").field(&self.get()).finish()
64    }
65}
66
67impl<T> From<T> for LockedCell<T> {
68    fn from(value: T) -> Self {
69        LockedCell(Cell::from(value))
70    }
71}
72
73impl<T> PartialEq for LockedCell<T>
74where
75    T: PartialEq + Copy,
76{
77    fn eq(&self, other: &Self) -> bool {
78        self.get() == other.get()
79    }
80}
81
82impl<T> Eq for LockedCell<T> where T: Eq + Copy {}
83
84impl<T> PartialOrd for LockedCell<T>
85where
86    T: PartialOrd + Copy,
87{
88    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
89        self.get().partial_cmp(&other.get())
90    }
91}
92
93impl<T> Ord for LockedCell<T>
94where
95    T: Ord + Copy,
96{
97    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
98        self.get().cmp(&other.get())
99    }
100}
101
102impl<T: ?Sized> Unlock for LockedCell<T> {
103    type Unlocked = core::cell::Cell<T>;
104
105    unsafe fn unlock_unchecked(&self) -> &Self::Unlocked {
106        &self.0
107    }
108}
109
110unsafe impl<T: Copy + Collect> Collect for LockedCell<T> {
111    const NEEDS_TRACE: bool = T::NEEDS_TRACE;
112
113    fn trace(&self, c: &crate::Collector) {
114        self.get().trace(c)
115    }
116}
117
118#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
119#[repr(transparent)]
120pub struct LockedRefCell<T: ?Sized>(core::cell::RefCell<T>);
121
122impl<T> LockedRefCell<T> {
123    pub const fn new(value: T) -> LockedRefCell<T> {
124        Self(RefCell::new(value))
125    }
126
127    pub fn into_inner(self) -> T {
128        self.0.into_inner()
129    }
130}
131
132impl<T> LockedRefCell<T>
133where
134    T: ?Sized,
135{
136    pub fn borrow(&self) -> core::cell::Ref<'_, T> {
137        self.0.borrow()
138    }
139
140    pub fn try_borrow(&self) -> Result<core::cell::Ref<'_, T>, core::cell::BorrowError> {
141        self.0.try_borrow()
142    }
143
144    pub fn as_ptr(&self) -> *mut T {
145        self.0.as_ptr()
146    }
147
148    pub fn get_mut(&mut self) -> &mut T {
149        self.0.get_mut()
150    }
151}
152
153impl<T: ?Sized> Unlock for LockedRefCell<T> {
154    type Unlocked = core::cell::RefCell<T>;
155
156    unsafe fn unlock_unchecked(&self) -> &Self::Unlocked {
157        &self.0
158    }
159}
160
161unsafe impl<T: ?Sized + Collect> Collect for LockedRefCell<T> {
162    const NEEDS_TRACE: bool = T::NEEDS_TRACE;
163
164    fn trace(&self, c: &crate::Collector) {
165        self.borrow().trace(c);
166    }
167}
168
169#[derive(Debug, Default, Clone, PartialEq, Eq)]
170#[repr(transparent)]
171pub struct LockedOnceCell<T>(core::cell::OnceCell<T>);
172
173impl<T> LockedOnceCell<T> {
174    pub const fn new() -> LockedOnceCell<T> {
175        LockedOnceCell(OnceCell::new())
176    }
177
178    pub fn get(&self) -> Option<&T> {
179        self.0.get()
180    }
181
182    pub fn get_mut(&mut self) -> Option<&mut T> {
183        self.0.get_mut()
184    }
185
186    pub fn into_inner(self) -> Option<T> {
187        self.0.into_inner()
188    }
189
190    pub fn take(&mut self) -> Option<T> {
191        self.0.take()
192    }
193}
194
195impl<T> Unlock for LockedOnceCell<T> {
196    type Unlocked = core::cell::OnceCell<T>;
197
198    unsafe fn unlock_unchecked(&self) -> &Self::Unlocked {
199        &self.0
200    }
201}
202
203unsafe impl<T: Collect> Collect for LockedOnceCell<T> {
204    const NEEDS_TRACE: bool = T::NEEDS_TRACE;
205
206    fn trace(&self, c: &crate::Collector) {
207        self.get().trace(c);
208    }
209}