|
| 1 | +use core::alloc::Allocator; |
| 2 | +use core::marker::PhantomData; |
| 3 | + |
| 4 | +use crate::raw_rc::RefCounter; |
| 5 | +use crate::raw_rc::raw_rc::RawRc; |
| 6 | +use crate::raw_rc::raw_weak::RawWeak; |
| 7 | +use crate::raw_rc::rc_value_pointer::RcValuePointer; |
| 8 | + |
| 9 | +/// A uniquely owned `RawRc` that allows multiple weak references but only one strong reference. |
| 10 | +/// `RawUniqueRc` does not implement `Drop`, user should call `RawUniqueRc::drop` manually to drop |
| 11 | +/// this object. |
| 12 | +#[repr(transparent)] |
| 13 | +pub(crate) struct RawUniqueRc<T, A> |
| 14 | +where |
| 15 | + T: ?Sized, |
| 16 | +{ |
| 17 | + // A `RawUniqueRc` is just a non-danging `RawWeak` that has zero strong count but with the value |
| 18 | + // initialized. |
| 19 | + weak: RawWeak<T, A>, |
| 20 | + |
| 21 | + // Defines the ownership of `T` for drop-check. |
| 22 | + _marker: PhantomData<T>, |
| 23 | + |
| 24 | + // Invariance is necessary for soundness: once other `RawWeak` references exist, we already have |
| 25 | + // a form of shared mutability! |
| 26 | + _marker2: PhantomData<*mut T>, |
| 27 | +} |
| 28 | + |
| 29 | +impl<T, A> RawUniqueRc<T, A> |
| 30 | +where |
| 31 | + T: ?Sized, |
| 32 | +{ |
| 33 | + /// Increments the weak count and returns the corresponding `RawWeak` object. |
| 34 | + /// |
| 35 | + /// # Safety |
| 36 | + /// |
| 37 | + /// - `self`, derived `RawWeak` or `RawRc` should only be handled by the same `RefCounter` |
| 38 | + /// implementation. |
| 39 | + pub(crate) unsafe fn downgrade<R>(&self) -> RawWeak<T, A> |
| 40 | + where |
| 41 | + A: Clone, |
| 42 | + R: RefCounter, |
| 43 | + { |
| 44 | + // SAFETY: Caller guarantees we only use the same `Rc` implementation and `self.weak` |
| 45 | + // is never dangling. |
| 46 | + unsafe { self.weak.clone_unchecked::<R>() } |
| 47 | + } |
| 48 | + |
| 49 | + pub(crate) unsafe fn drop<R>(&mut self) |
| 50 | + where |
| 51 | + A: Allocator, |
| 52 | + R: RefCounter, |
| 53 | + { |
| 54 | + unsafe { self.weak.assume_init_drop::<R>() }; |
| 55 | + } |
| 56 | + |
| 57 | + pub(crate) unsafe fn into_rc<R>(self) -> RawRc<T, A> |
| 58 | + where |
| 59 | + R: RefCounter, |
| 60 | + { |
| 61 | + unsafe fn inner<R>(value_ptr: RcValuePointer) |
| 62 | + where |
| 63 | + R: RefCounter, |
| 64 | + { |
| 65 | + unsafe { R::from_raw_counter(value_ptr.strong_count_ptr().as_ref()) } |
| 66 | + .unlock_strong_count(); |
| 67 | + } |
| 68 | + |
| 69 | + unsafe { |
| 70 | + inner::<R>(self.weak.value_ptr_unchecked()); |
| 71 | + |
| 72 | + RawRc::from_weak(self.weak) |
| 73 | + } |
| 74 | + } |
| 75 | +} |
0 commit comments