1use core::{
4 cell::{BorrowError, BorrowMutError, Cell, Ref, RefCell, RefMut},
5 cmp::Ordering,
6 fmt,
7};
8
9use crate::{barrier::Unlock, Collect, Collection, Gc, Mutation};
10
11macro_rules! make_lock_wrapper {
13 (
14 $(#[$meta:meta])*
15 locked = $locked_type:ident as $gc_locked_type:ident;
16 unlocked = $unlocked_type:ident unsafe $unsafe_unlock_method:ident;
17 impl Sized { $($sized_items:tt)* }
18 impl ?Sized { $($unsized_items:tt)* }
19 ) => {
20 #[doc = stringify!($unlocked_type)]
22 #[doc = stringify!($unlocked_type)]
26 #[doc = stringify!($locked_type)]
30 $(#[$meta])*
33 #[repr(transparent)]
34 pub struct $locked_type<T: ?Sized> {
35 cell: $unlocked_type<T>,
36 }
37
38 #[doc = concat!("An alias for `Gc<'gc, ", stringify!($locked_type), "<T>>`.")]
39 pub type $gc_locked_type<'gc, T> = Gc<'gc, $locked_type<T>>;
40
41 impl<T> $locked_type<T> {
42 #[inline]
43 pub fn new(t: T) -> $locked_type<T> {
44 Self { cell: $unlocked_type::new(t) }
45 }
46
47 #[inline]
48 pub fn into_inner(self) -> T {
49 self.cell.into_inner()
50 }
51
52 $($sized_items)*
53 }
54
55 impl<T: ?Sized> $locked_type<T> {
56 #[inline]
57 pub fn as_ptr(&self) -> *mut T {
58 self.cell.as_ptr()
59 }
60
61 $($unsized_items)*
62
63 #[doc = concat!("Access the wrapped [`", stringify!($unlocked_type), "`].")]
64 #[doc = stringify!($unlocked_type)]
70 #[inline]
73 pub unsafe fn $unsafe_unlock_method(&self) -> &$unlocked_type<T> {
74 &self.cell
75 }
76
77 #[inline]
78 pub fn get_mut(&mut self) -> &mut T {
79 self.cell.get_mut()
80 }
81 }
82
83 impl<T: ?Sized> Unlock for $locked_type<T> {
84 type Unlocked = $unlocked_type<T>;
85
86 #[inline]
87 unsafe fn unlock_unchecked(&self) -> &Self::Unlocked {
88 &self.cell
89 }
90 }
91
92 impl<T> From<T> for $locked_type<T> {
93 #[inline]
94 fn from(t: T) -> Self {
95 Self::new(t)
96 }
97 }
98
99 impl<T> From<$unlocked_type<T>> for $locked_type<T> {
100 #[inline]
101 fn from(cell: $unlocked_type<T>) -> Self {
102 Self { cell }
103 }
104 }
105 };
106}
107
108make_lock_wrapper!(
109 #[derive(Default)]
110 locked = Lock as GcLock;
111 unlocked = Cell unsafe as_cell;
112 impl Sized {
113 #[inline]
114 pub fn get(&self) -> T where T: Copy {
115 self.cell.get()
116 }
117
118 #[inline]
119 pub fn take(&self) -> T where T: Default {
120 self.cell.take()
131 }
132 }
133 impl ?Sized {}
134);
135
136impl<T: Copy + fmt::Debug> fmt::Debug for Lock<T> {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 f.debug_tuple("Lock").field(&self.cell).finish()
139 }
140}
141
142impl<'gc, T: Copy + 'gc> Gc<'gc, Lock<T>> {
143 #[inline]
144 pub fn get(self) -> T {
145 self.cell.get()
146 }
147
148 #[inline]
149 pub fn set(self, mc: &Mutation<'gc>, t: T) {
150 self.unlock(mc).set(t);
151 }
152}
153
154unsafe impl<'gc, T: Collect + Copy + 'gc> Collect for Lock<T> {
155 #[inline]
156 fn needs_trace() -> bool {
157 T::needs_trace()
158 }
159
160 #[inline]
161 fn trace(&self, cc: &Collection) {
162 T::trace(&self.get(), cc);
179 }
180}
181
182impl<T: Copy> Clone for Lock<T> {
184 #[inline]
185 fn clone(&self) -> Self {
186 Self::new(self.get())
187 }
188}
189
190impl<T: PartialEq + Copy> PartialEq for Lock<T> {
192 #[inline]
193 fn eq(&self, other: &Self) -> bool {
194 self.get() == other.get()
195 }
196}
197
198impl<T: Eq + Copy> Eq for Lock<T> {}
200
201impl<T: PartialOrd + Copy> PartialOrd for Lock<T> {
203 #[inline]
204 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
205 self.get().partial_cmp(&other.get())
206 }
207}
208
209impl<T: Ord + Copy> Ord for Lock<T> {
211 #[inline]
212 fn cmp(&self, other: &Self) -> Ordering {
213 self.get().cmp(&other.get())
214 }
215}
216
217make_lock_wrapper!(
218 #[derive(Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
219 locked = RefLock as GcRefLock;
220 unlocked = RefCell unsafe as_ref_cell;
221 impl Sized {
222 #[inline]
223 pub fn take(&self) -> T where T: Default {
224 self.cell.take()
226 }
227 }
228 impl ?Sized {
229 #[track_caller]
230 #[inline]
231 pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
232 self.cell.borrow()
233 }
234
235 #[inline]
236 pub fn try_borrow<'a>(&'a self) -> Result<Ref<'a, T>, BorrowError> {
237 self.cell.try_borrow()
238 }
239 }
240);
241
242impl<T: fmt::Debug + ?Sized> fmt::Debug for RefLock<T> {
243 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
244 let mut fmt = fmt.debug_tuple("RefLock");
245 match self.try_borrow() {
246 Ok(borrow) => fmt.field(&borrow),
247 Err(_) => {
248 struct BorrowedPlaceholder;
251
252 impl fmt::Debug for BorrowedPlaceholder {
253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254 f.write_str("<borrowed>")
255 }
256 }
257
258 fmt.field(&BorrowedPlaceholder)
259 }
260 }
261 .finish()
262 }
263}
264
265impl<'gc, T: ?Sized + 'gc> Gc<'gc, RefLock<T>> {
266 #[track_caller]
267 #[inline]
268 pub fn borrow(self) -> Ref<'gc, T> {
269 RefLock::borrow(self.as_ref())
270 }
271
272 #[inline]
273 pub fn try_borrow(self) -> Result<Ref<'gc, T>, BorrowError> {
274 RefLock::try_borrow(self.as_ref())
275 }
276
277 #[track_caller]
278 #[inline]
279 pub fn borrow_mut(self, mc: &Mutation<'gc>) -> RefMut<'gc, T> {
280 self.unlock(mc).borrow_mut()
281 }
282
283 #[inline]
284 pub fn try_borrow_mut(self, mc: &Mutation<'gc>) -> Result<RefMut<'gc, T>, BorrowMutError> {
285 self.unlock(mc).try_borrow_mut()
286 }
287}
288
289unsafe impl<'gc, T: Collect + 'gc> Collect for RefLock<T> {
295 #[inline]
296 fn needs_trace() -> bool {
297 T::needs_trace()
298 }
299
300 #[inline]
301 fn trace(&self, cc: &Collection) {
302 self.borrow().trace(cc);
303 }
304}