Skip to content

Commit 468923f

Browse files
committed
Add RawUniqueRc type
1 parent 857ecce commit 468923f

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

library/alloc/src/raw_rc/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use core::mem;
6767
use core::sync::atomic::Atomic;
6868

6969
mod raw_rc;
70+
mod raw_unique_rc;
7071
mod raw_weak;
7172
mod rc_alloc;
7273
mod rc_layout;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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

Comments
 (0)