1 | /*! |
2 | This create provides weak pointers for [`Pin`]`<`[`Rc<T>`]`>` and [`Pin`]`<`[`Arc<T>`]`>` |
3 | |
4 | ## Motivation |
5 | |
6 | [`Pin`]`<`[`Rc<T>`]`>` and [`Pin`]`<`[`Arc<T>`]`>` cannot be converted safely to |
7 | their `Weak<T>` equivalent if `T` does not implement [`Unpin`]. |
8 | That's because it would otherwise be possible to do something like this: |
9 | |
10 | ```no_run |
11 | # use std::{pin::Pin, marker::PhantomPinned, rc::{Rc, Weak}}; |
12 | struct SomeStruct(PhantomPinned); |
13 | let pinned = Rc::pin(SomeStruct(PhantomPinned)); |
14 | |
15 | // This is unsound !!! |
16 | let weak = unsafe { |
17 | Rc::downgrade(&Pin::into_inner_unchecked(pinned.clone())) |
18 | }; |
19 | |
20 | // ... because otherwise it would be possible to move the content of pinned: |
21 | let mut unpinned_rc = weak.upgrade().unwrap(); |
22 | std::mem::drop((pinned, weak)); |
23 | // unpinned_rc is now the only reference so this will work: |
24 | let x = std::mem::replace( |
25 | Rc::get_mut(&mut unpinned_rc).unwrap(), |
26 | SomeStruct(PhantomPinned), |
27 | ); |
28 | ``` |
29 | |
30 | In that example, `x` is the original `SomeStruct` which we moved in memory, |
31 | **that is undefined behavior**, do not do that at home. |
32 | |
33 | ## `PinWeak` |
34 | |
35 | This crate simply provide a [`rc::PinWeak`] and [`sync::PinWeak`] which allow to |
36 | get weak pointer from `Pin<std::rc::Rc>` and `Pin<std::sync::Arc>`. |
37 | |
38 | This is safe because you can one can only get back a `Pin` out of it when |
39 | trying to upgrade the weak pointer. |
40 | |
41 | `PinWeak` can be created using the `PinWeak` downgrade function. |
42 | |
43 | ## Example |
44 | |
45 | ``` |
46 | use pin_weak::rc::*; |
47 | # use std::marker::PhantomPinned; |
48 | struct SomeStruct(PhantomPinned, usize); |
49 | let pinned = Rc::pin(SomeStruct(PhantomPinned, 42)); |
50 | let weak = PinWeak::downgrade(pinned.clone()); |
51 | assert_eq!(weak.upgrade().unwrap().1, 42); |
52 | std::mem::drop(pinned); |
53 | assert!(weak.upgrade().is_none()); |
54 | ``` |
55 | |
56 | */ |
57 | |
58 | #![no_std ] |
59 | extern crate alloc; |
60 | |
61 | #[cfg (doc)] |
62 | use alloc::{rc::Rc, sync::Arc}; |
63 | #[cfg (doc)] |
64 | use core::pin::Pin; |
65 | |
66 | /// The implementation is in a macro because it is repeated for Arc and Rc |
67 | macro_rules! implementation { |
68 | ($Rc:ident, $Weak:ident, $rc_lit:literal) => { |
69 | #[doc(no_inline)] |
70 | /// re-exported for convenience |
71 | pub use core::pin::Pin; |
72 | /// This is a safe wrapper around something that could be compared to [`Pin`]`<`[`Weak<T>`]`>` |
73 | /// |
74 | /// The typical way to obtain a `PinWeak` is to call [`PinWeak::downgrade`] |
75 | #[derive(Debug)] |
76 | pub struct PinWeak<T: ?Sized>(Weak<T>); |
77 | impl<T> Default for PinWeak<T> { |
78 | fn default() -> Self { |
79 | Self(Weak::default()) |
80 | } |
81 | } |
82 | impl<T: ?Sized> Clone for PinWeak<T> { |
83 | fn clone(&self) -> Self { |
84 | Self(self.0.clone()) |
85 | } |
86 | } |
87 | impl<T: ?Sized> PinWeak<T> { |
88 | #[doc = concat!("Equivalent function to [`" , $rc_lit, "::downgrade`], but taking a `Pin<" , $rc_lit, "<T>>` instead." )] |
89 | pub fn downgrade(rc: Pin<$Rc<T>>) -> Self { |
90 | // Safety: we will never return anything else than a Pin<Rc> |
91 | unsafe { Self($Rc::downgrade(&Pin::into_inner_unchecked(rc))) } |
92 | } |
93 | #[doc = concat!("Equivalent function to [`Weak::upgrade`], but taking a `Pin<" , $rc_lit, "<T>>` instead." )] |
94 | pub fn upgrade(&self) -> Option<Pin<$Rc<T>>> { |
95 | // Safety: the weak was constructed from a Pin<Rc<T>> |
96 | self.0.upgrade().map(|rc| unsafe { Pin::new_unchecked(rc) }) |
97 | } |
98 | |
99 | /// Equivalent to [`Weak::strong_count`] |
100 | pub fn strong_count(&self) -> usize { |
101 | self.0.strong_count() |
102 | } |
103 | |
104 | /// Equivalent to [`Weak::weak_count`] |
105 | pub fn weak_count(&self) -> usize { |
106 | self.0.weak_count() |
107 | } |
108 | |
109 | /// Equivalent to [`Weak::ptr_eq`] |
110 | pub fn ptr_eq(&self, other: &Self) -> bool { |
111 | self.0.ptr_eq(&other.0) |
112 | } |
113 | } |
114 | |
115 | #[test] |
116 | fn test() { |
117 | struct Foo { |
118 | _p: core::marker::PhantomPinned, |
119 | u: u32, |
120 | } |
121 | impl Foo { |
122 | fn new(u: u32) -> Self { |
123 | Self { _p: core::marker::PhantomPinned, u } |
124 | } |
125 | } |
126 | let c = $Rc::pin(Foo::new(44)); |
127 | let weak1 = PinWeak::downgrade(c.clone()); |
128 | assert_eq!(weak1.upgrade().unwrap().u, 44); |
129 | assert_eq!(weak1.clone().upgrade().unwrap().u, 44); |
130 | assert_eq!(weak1.strong_count(), 1); |
131 | assert_eq!(weak1.weak_count(), 1); |
132 | let weak2 = PinWeak::downgrade(c.clone()); |
133 | assert_eq!(weak2.upgrade().unwrap().u, 44); |
134 | assert_eq!(weak1.upgrade().unwrap().u, 44); |
135 | assert_eq!(weak2.strong_count(), 1); |
136 | assert_eq!(weak2.weak_count(), 2); |
137 | assert!(weak1.ptr_eq(&weak2)); |
138 | assert!(!weak1.ptr_eq(&Default::default())); |
139 | // note that this moves c and therefore it will be dropped |
140 | let weak3 = PinWeak::downgrade(c); |
141 | assert!(weak3.upgrade().is_none()); |
142 | assert!(weak2.upgrade().is_none()); |
143 | assert!(weak1.upgrade().is_none()); |
144 | assert!(weak1.clone().upgrade().is_none()); |
145 | assert_eq!(weak2.strong_count(), 0); |
146 | assert_eq!(weak2.weak_count(), 0); |
147 | |
148 | let def = PinWeak::<alloc::boxed::Box<&'static mut ()>>::default(); |
149 | assert!(def.upgrade().is_none()); |
150 | assert!(def.clone().upgrade().is_none()); |
151 | } |
152 | }; |
153 | } |
154 | |
155 | pub mod rc { |
156 | #[doc (no_inline)] |
157 | /// re-exported for convenience |
158 | pub use alloc::rc::{Rc, Weak}; |
159 | implementation! {Rc, Weak, "Rc" } |
160 | } |
161 | |
162 | #[cfg (feature = "sync" )] |
163 | pub mod sync { |
164 | #[doc (no_inline)] |
165 | /// re-exported for convenience |
166 | pub use alloc::sync::{Arc, Weak}; |
167 | implementation! {Arc, Weak, "Arc" } |
168 | } |
169 | |