1use crate::{
4 Tracer,
5 trace::{Finalize, Trace},
6};
7use std::marker::PhantomData;
8use std::ptr::NonNull;
9use std::{
10 cell::{Cell, UnsafeCell},
11 cmp::Ordering,
12 fmt::{self, Debug, Display},
13 hash::Hash,
14 ops::{Deref, DerefMut},
15};
16
17#[derive(Copy, Clone)]
20struct BorrowFlag(usize);
21
22#[derive(Copy, Clone, Debug, Eq, PartialEq)]
28enum BorrowState {
29 Reading,
30 Writing,
31 Unused,
32}
33
34const WRITING: usize = !0;
35const UNUSED: usize = 0;
36
37const BORROWFLAG_INIT: BorrowFlag = BorrowFlag(UNUSED);
39
40impl BorrowFlag {
41 const fn borrowed(self) -> BorrowState {
43 match self.0 {
44 UNUSED => BorrowState::Unused,
45 WRITING => BorrowState::Writing,
46 _ => BorrowState::Reading,
47 }
48 }
49
50 const fn set_writing(self) -> Self {
52 Self(self.0 | WRITING)
53 }
54
55 #[inline]
61 fn add_reading(self) -> Self {
62 assert_ne!(self.borrowed(), BorrowState::Writing);
63 let flags = Self(self.0 + 1);
64
65 {
68 assert_eq!(flags.borrowed(), BorrowState::Reading);
69 }
70 flags
71 }
72
73 fn sub_reading(self) -> Self {
78 assert_eq!(self.borrowed(), BorrowState::Reading);
79 Self(self.0 - 1)
80 }
81}
82
83impl Debug for BorrowFlag {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 f.debug_struct("BorrowFlag")
86 .field("State", &self.borrowed())
87 .finish()
88 }
89}
90
91pub struct GcRefCell<T: ?Sized + 'static> {
96 borrow: Cell<BorrowFlag>,
97 cell: UnsafeCell<T>,
98}
99
100impl<T> GcRefCell<T> {
101 pub const fn new(value: T) -> Self {
103 Self {
104 borrow: Cell::new(BORROWFLAG_INIT),
105 cell: UnsafeCell::new(value),
106 }
107 }
108
109 pub fn into_inner(self) -> T {
111 self.cell.into_inner()
112 }
113}
114
115impl<T: ?Sized> GcRefCell<T> {
116 pub fn borrow(&self) -> GcRef<'_, T> {
125 match self.try_borrow() {
126 Ok(value) => value,
127 Err(e) => panic!("{}", e),
128 }
129 }
130
131 #[track_caller]
140 pub fn borrow_mut(&self) -> GcRefMut<'_, T> {
141 match self.try_borrow_mut() {
142 Ok(value) => value,
143 Err(e) => panic!("{}", e),
144 }
145 }
146
147 pub fn try_borrow(&self) -> Result<GcRef<'_, T>, BorrowError> {
159 if self.borrow.get().borrowed() == BorrowState::Writing {
160 return Err(BorrowError);
161 }
162 self.borrow.set(self.borrow.get().add_reading());
163
164 unsafe {
166 Ok(GcRef {
167 borrow: BorrowGcRef {
168 borrow: &self.borrow,
169 },
170 value: NonNull::new_unchecked(self.cell.get()),
171 })
172 }
173 }
174
175 pub fn try_borrow_mut(&self) -> Result<GcRefMut<'_, T>, BorrowMutError> {
186 if self.borrow.get().borrowed() != BorrowState::Unused {
187 return Err(BorrowMutError);
188 }
189 self.borrow.set(self.borrow.get().set_writing());
190
191 unsafe {
194 Ok(GcRefMut {
195 borrow: BorrowGcRefMut {
196 borrow: &self.borrow,
197 },
198 value: NonNull::new_unchecked(self.cell.get()),
199 marker: PhantomData,
200 })
201 }
202 }
203}
204
205#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Default, Hash)]
207pub struct BorrowError;
208
209impl Display for BorrowError {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 Display::fmt("GcCell<T> already mutably borrowed", f)
212 }
213}
214
215#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Default, Hash)]
217pub struct BorrowMutError;
218
219impl Display for BorrowMutError {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 Display::fmt("GcCell<T> already borrowed", f)
222 }
223}
224
225impl<T: Trace + ?Sized> Finalize for GcRefCell<T> {}
226
227unsafe impl<T: Trace + ?Sized> Trace for GcRefCell<T> {
232 unsafe fn trace(&self, tracer: &mut Tracer) {
233 match self.borrow.get().borrowed() {
234 BorrowState::Writing => (),
235 _ => unsafe { (*self.cell.get()).trace(tracer) },
237 }
238 }
239
240 unsafe fn trace_non_roots(&self) {
241 match self.borrow.get().borrowed() {
242 BorrowState::Writing => (),
243 _ => unsafe { (*self.cell.get()).trace_non_roots() },
245 }
246 }
247
248 fn run_finalizer(&self) {
249 Finalize::finalize(self);
250 match self.borrow.get().borrowed() {
251 BorrowState::Writing => (),
252 _ => unsafe { (*self.cell.get()).run_finalizer() },
254 }
255 }
256}
257
258struct BorrowGcRef<'a> {
259 borrow: &'a Cell<BorrowFlag>,
260}
261
262impl Drop for BorrowGcRef<'_> {
263 fn drop(&mut self) {
264 debug_assert_eq!(self.borrow.get().borrowed(), BorrowState::Reading);
265 self.borrow.set(self.borrow.get().sub_reading());
266 }
267}
268
269impl Clone for BorrowGcRef<'_> {
270 #[inline]
271 fn clone(&self) -> Self {
272 self.borrow.set(self.borrow.get().add_reading());
273 BorrowGcRef {
274 borrow: self.borrow,
275 }
276 }
277}
278
279pub struct GcRef<'a, T: ?Sized + 'static> {
281 value: NonNull<T>,
282 borrow: BorrowGcRef<'a>,
283}
284
285impl<'a, T: ?Sized> GcRef<'a, T> {
286 #[must_use]
291 pub unsafe fn cast<U>(orig: Self) -> GcRef<'a, U> {
292 let value = orig.value.cast::<U>();
293
294 GcRef {
295 borrow: orig.borrow,
296 value,
297 }
298 }
299
300 #[allow(clippy::should_implement_trait)]
309 #[must_use]
310 pub fn clone(orig: &GcRef<'a, T>) -> GcRef<'a, T> {
311 GcRef {
312 borrow: orig.borrow.clone(),
313 value: orig.value,
314 }
315 }
316
317 pub fn try_map<U, F>(orig: Self, f: F) -> Option<GcRef<'a, U>>
326 where
327 U: ?Sized,
328 F: FnOnce(&T) -> Option<&U>,
329 {
330 let value = NonNull::from(f(&*orig)?);
331
332 let ret = GcRef {
333 borrow: orig.borrow,
334 value,
335 };
336
337 Some(ret)
338 }
339
340 pub fn map<U, F>(orig: Self, f: F) -> GcRef<'a, U>
348 where
349 U: ?Sized,
350 F: FnOnce(&T) -> &U,
351 {
352 let value = NonNull::from(f(&*orig));
353
354 GcRef {
355 borrow: orig.borrow,
356 value,
357 }
358 }
359
360 pub fn map_split<U, V, F>(orig: Self, f: F) -> (GcRef<'a, U>, GcRef<'a, V>)
367 where
368 U: ?Sized,
369 V: ?Sized,
370 F: FnOnce(&T) -> (&U, &V),
371 {
372 let (a, b) = f(&*orig);
373 let borrow = orig.borrow.clone();
374
375 (
376 GcRef {
377 borrow,
378 value: NonNull::from(a),
379 },
380 GcRef {
381 value: NonNull::from(b),
382 borrow: orig.borrow,
383 },
384 )
385 }
386}
387
388impl<T: ?Sized> Deref for GcRef<'_, T> {
389 type Target = T;
390
391 fn deref(&self) -> &T {
392 unsafe { self.value.as_ref() }
393 }
394}
395
396impl<T: ?Sized + Debug> Debug for GcRef<'_, T> {
397 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398 Debug::fmt(&**self, f)
399 }
400}
401
402impl<T: ?Sized + Display> Display for GcRef<'_, T> {
403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404 Display::fmt(&**self, f)
405 }
406}
407
408struct BorrowGcRefMut<'a> {
409 borrow: &'a Cell<BorrowFlag>,
410}
411
412impl Drop for BorrowGcRefMut<'_> {
413 fn drop(&mut self) {
414 debug_assert_eq!(self.borrow.get().borrowed(), BorrowState::Writing);
415 self.borrow.set(BorrowFlag(UNUSED));
416 }
417}
418
419pub struct GcRefMut<'a, T: ?Sized> {
421 value: NonNull<T>,
425 borrow: BorrowGcRefMut<'a>,
426 marker: PhantomData<&'a mut T>,
428}
429
430impl<'a, T: ?Sized> GcRefMut<'a, T> {
431 #[must_use]
436 pub unsafe fn cast<V>(orig: Self) -> GcRefMut<'a, V> {
437 let value = orig.value.cast::<V>();
438
439 GcRefMut {
440 borrow: orig.borrow,
441 value,
442 marker: PhantomData,
443 }
444 }
445
446 pub fn try_map<V, F>(mut orig: GcRefMut<'a, T>, f: F) -> Option<GcRefMut<'a, V>>
455 where
456 V: ?Sized,
457 F: FnOnce(&mut T) -> Option<&mut V>,
458 {
459 let value = NonNull::from(f(&mut *orig)?);
460
461 let ret = GcRefMut {
462 borrow: orig.borrow,
463 value,
464 marker: PhantomData,
465 };
466
467 Some(ret)
468 }
469
470 pub fn map<V, F>(mut orig: Self, f: F) -> GcRefMut<'a, V>
479 where
480 V: ?Sized,
481 F: FnOnce(&mut T) -> &mut V,
482 {
483 let value = NonNull::from(f(&mut *orig));
484
485 GcRefMut {
486 borrow: orig.borrow,
487 value,
488 marker: PhantomData,
489 }
490 }
491}
492
493impl<T: ?Sized> Deref for GcRefMut<'_, T> {
494 type Target = T;
495
496 fn deref(&self) -> &T {
497 unsafe { self.value.as_ref() }
499 }
500}
501
502impl<T: ?Sized> DerefMut for GcRefMut<'_, T> {
503 fn deref_mut(&mut self) -> &mut T {
504 unsafe { self.value.as_mut() }
506 }
507}
508
509impl<T: Debug + ?Sized> Debug for GcRefMut<'_, T> {
510 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
511 Debug::fmt(&**self, f)
512 }
513}
514
515impl<T: Display + ?Sized> Display for GcRefMut<'_, T> {
516 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
517 Display::fmt(&**self, f)
518 }
519}
520
521unsafe impl<T: ?Sized + Send> Send for GcRefCell<T> {}
523
524impl<T: Trace + Clone> Clone for GcRefCell<T> {
525 fn clone(&self) -> Self {
526 Self::new(self.borrow().clone())
527 }
528}
529
530impl<T: Default> Default for GcRefCell<T> {
531 fn default() -> Self {
532 Self::new(Default::default())
533 }
534}
535
536#[allow(clippy::inline_always)]
537impl<T: ?Sized + PartialEq> PartialEq for GcRefCell<T> {
538 #[inline(always)]
539 fn eq(&self, other: &Self) -> bool {
540 *self.borrow() == *other.borrow()
541 }
542}
543
544impl<T: ?Sized + Eq> Eq for GcRefCell<T> {}
545
546#[allow(clippy::inline_always)]
547impl<T: ?Sized + PartialOrd> PartialOrd for GcRefCell<T> {
548 #[inline(always)]
549 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
550 (*self.borrow()).partial_cmp(&*other.borrow())
551 }
552
553 #[inline(always)]
554 fn lt(&self, other: &Self) -> bool {
555 *self.borrow() < *other.borrow()
556 }
557
558 #[inline(always)]
559 fn le(&self, other: &Self) -> bool {
560 *self.borrow() <= *other.borrow()
561 }
562
563 #[inline(always)]
564 fn gt(&self, other: &Self) -> bool {
565 *self.borrow() > *other.borrow()
566 }
567
568 #[inline(always)]
569 fn ge(&self, other: &Self) -> bool {
570 *self.borrow() >= *other.borrow()
571 }
572}
573
574impl<T: ?Sized + Ord> Ord for GcRefCell<T> {
575 fn cmp(&self, other: &Self) -> Ordering {
576 (*self.borrow()).cmp(&*other.borrow())
577 }
578}
579
580impl<T: ?Sized + Debug> Debug for GcRefCell<T> {
581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
582 match self.borrow.get().borrowed() {
583 BorrowState::Unused | BorrowState::Reading => f
584 .debug_struct("GcCell")
585 .field("flags", &self.borrow.get())
586 .field("value", &self.borrow())
587 .finish_non_exhaustive(),
588 BorrowState::Writing => f
589 .debug_struct("GcCell")
590 .field("flags", &self.borrow.get())
591 .field("value", &"<borrowed>")
592 .finish_non_exhaustive(),
593 }
594 }
595}