/rust/registry/src/index.crates.io-1949cf8c6b5b557f/arc-swap-1.9.1/src/ref_cnt.rs
Line | Count | Source |
1 | | use core::mem; |
2 | | #[rustversion::since(1.39)] |
3 | | use core::pin::Pin; |
4 | | use core::ptr; |
5 | | |
6 | | use crate::imports::{Arc, Rc}; |
7 | | |
8 | | /// A trait describing smart reference counted pointers. |
9 | | /// |
10 | | /// Note that in a way [`Option<Arc<T>>`][Option] is also a smart reference counted pointer, just |
11 | | /// one that can hold NULL. |
12 | | /// |
13 | | /// The trait is unsafe, because a wrong implementation will break the [ArcSwapAny] |
14 | | /// implementation and lead to UB. |
15 | | /// |
16 | | /// This is not actually expected for downstream crate to implement, this is just means to reuse |
17 | | /// code for [Arc] and [`Option<Arc>`][Option] variants. However, it is theoretically possible (if |
18 | | /// you have your own [Arc] implementation). |
19 | | /// |
20 | | /// It is also implemented for [Rc], but that is not considered very useful (because the |
21 | | /// [ArcSwapAny] is not `Send` or `Sync`, therefore there's very little advantage for it to be |
22 | | /// atomic). |
23 | | /// |
24 | | /// # Safety |
25 | | /// |
26 | | /// Aside from the obvious properties (like that incrementing and decrementing a reference count |
27 | | /// cancel each out and that having less references tracked than how many things actually point to |
28 | | /// the value is fine as long as the count doesn't drop to 0), it also must satisfy that if two |
29 | | /// pointers have the same value, they point to the same object. This is specifically not true for |
30 | | /// ZSTs, but it is true for `Arc`s of ZSTs, because they have the reference counts just after the |
31 | | /// value. It would be fine to point to a type-erased version of the same object, though (if one |
32 | | /// could use this trait with unsized types in the first place). |
33 | | /// |
34 | | /// Furthermore, the type should be Pin (eg. if the type is cloned or moved, it should still |
35 | | /// point/deref to the same place in memory). |
36 | | /// |
37 | | /// [Arc]: std::sync::Arc |
38 | | /// [Rc]: std::rc::Rc |
39 | | /// [ArcSwapAny]: crate::ArcSwapAny |
40 | | pub unsafe trait RefCnt: Clone { |
41 | | /// The base type the pointer points to. |
42 | | type Base; |
43 | | |
44 | | /// Converts the smart pointer into a raw pointer, without affecting the reference count. |
45 | | /// |
46 | | /// This can be seen as kind of freezing the pointer ‒ it'll be later converted back using |
47 | | /// [`from_ptr`](#method.from_ptr). |
48 | | /// |
49 | | /// The pointer must point to the value stored (and the value must be the same as one returned |
50 | | /// by [`as_ptr`](#method.as_ptr). |
51 | | fn into_ptr(me: Self) -> *mut Self::Base; |
52 | | |
53 | | /// Provides a view into the smart pointer as a raw pointer. |
54 | | /// |
55 | | /// This must not affect the reference count ‒ the pointer is only borrowed. |
56 | | fn as_ptr(me: &Self) -> *mut Self::Base; |
57 | | |
58 | | /// Converts a raw pointer back into the smart pointer, without affecting the reference count. |
59 | | /// |
60 | | /// This is only called on values previously returned by [`into_ptr`](#method.into_ptr). |
61 | | /// However, it is not guaranteed to be 1:1 relation ‒ `from_ptr` may be called more times than |
62 | | /// `into_ptr` temporarily provided the reference count never drops under 1 during that time |
63 | | /// (the implementation sometimes owes a reference). These extra pointers will either be |
64 | | /// converted back using `into_ptr` or forgotten. |
65 | | /// |
66 | | /// # Safety |
67 | | /// |
68 | | /// This must not be called by code outside of this crate. |
69 | | unsafe fn from_ptr(ptr: *const Self::Base) -> Self; |
70 | | |
71 | | /// Increments the reference count by one. |
72 | | /// |
73 | | /// Return the pointer to the inner thing as a side effect. |
74 | 62.9M | fn inc(me: &Self) -> *mut Self::Base { |
75 | 62.9M | Self::into_ptr(Self::clone(me)) |
76 | 62.9M | } <core::option::Option<alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>>> as arc_swap::ref_cnt::RefCnt>::inc Line | Count | Source | 74 | 62.9M | fn inc(me: &Self) -> *mut Self::Base { | 75 | 62.9M | Self::into_ptr(Self::clone(me)) | 76 | 62.9M | } |
Unexecuted instantiation: <alloc::sync::Arc<bytes::bytes::Bytes> as arc_swap::ref_cnt::RefCnt>::inc <alloc::sync::Arc<(u64, std::time::Instant)> as arc_swap::ref_cnt::RefCnt>::inc Line | Count | Source | 74 | 52.6k | fn inc(me: &Self) -> *mut Self::Base { | 75 | 52.6k | Self::into_ptr(Self::clone(me)) | 76 | 52.6k | } |
Unexecuted instantiation: <_ as arc_swap::ref_cnt::RefCnt>::inc |
77 | | |
78 | | /// Decrements the reference count by one. |
79 | | /// |
80 | | /// Note this is called on a raw pointer (one previously returned by |
81 | | /// [`into_ptr`](#method.into_ptr). This may lead to dropping of the reference count to 0 and |
82 | | /// destruction of the internal pointer. |
83 | | /// |
84 | | /// # Safety |
85 | | /// |
86 | | /// This must not be called by code outside of this crate. |
87 | 954k | unsafe fn dec(ptr: *const Self::Base) { |
88 | 954k | drop(Self::from_ptr(ptr)); |
89 | 954k | } <core::option::Option<alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>>> as arc_swap::ref_cnt::RefCnt>::dec Line | Count | Source | 87 | 928k | unsafe fn dec(ptr: *const Self::Base) { | 88 | 928k | drop(Self::from_ptr(ptr)); | 89 | 928k | } |
Unexecuted instantiation: <alloc::sync::Arc<bytes::bytes::Bytes> as arc_swap::ref_cnt::RefCnt>::dec <alloc::sync::Arc<(u64, std::time::Instant)> as arc_swap::ref_cnt::RefCnt>::dec Line | Count | Source | 87 | 26.2k | unsafe fn dec(ptr: *const Self::Base) { | 88 | 26.2k | drop(Self::from_ptr(ptr)); | 89 | 26.2k | } |
Unexecuted instantiation: <_ as arc_swap::ref_cnt::RefCnt>::dec |
90 | | } |
91 | | |
92 | | unsafe impl<T> RefCnt for Arc<T> { |
93 | | type Base = T; |
94 | 52.4M | fn into_ptr(me: Arc<T>) -> *mut T { |
95 | 52.4M | Arc::into_raw(me) as *mut T |
96 | 52.4M | } <alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>> as arc_swap::ref_cnt::RefCnt>::into_ptr Line | Count | Source | 94 | 52.3M | fn into_ptr(me: Arc<T>) -> *mut T { | 95 | 52.3M | Arc::into_raw(me) as *mut T | 96 | 52.3M | } |
Unexecuted instantiation: <alloc::sync::Arc<bytes::bytes::Bytes> as arc_swap::ref_cnt::RefCnt>::into_ptr <alloc::sync::Arc<(u64, std::time::Instant)> as arc_swap::ref_cnt::RefCnt>::into_ptr Line | Count | Source | 94 | 105k | fn into_ptr(me: Arc<T>) -> *mut T { | 95 | 105k | Arc::into_raw(me) as *mut T | 96 | 105k | } |
Unexecuted instantiation: <alloc::sync::Arc<_> as arc_swap::ref_cnt::RefCnt>::into_ptr |
97 | 90.0k | fn as_ptr(me: &Arc<T>) -> *mut T { |
98 | | // Slightly convoluted way to do this, but this avoids stacked borrows violations. The same |
99 | | // intention as |
100 | | // |
101 | | // me as &T as *const T as *mut T |
102 | | // |
103 | | // We first create a "shallow copy" of me - one that doesn't really own its ref count |
104 | | // (that's OK, me _does_ own it, so it can't be destroyed in the meantime). |
105 | | // Then we can use into_raw (which preserves not having the ref count). |
106 | | // |
107 | | // We need to "revert" the changes we did. In current std implementation, the combination |
108 | | // of from_raw and forget is no-op. But formally, into_raw shall be paired with from_raw |
109 | | // and that read shall be paired with forget to properly "close the brackets". In future |
110 | | // versions of STD, these may become something else that's not really no-op (unlikely, but |
111 | | // possible), so we future-proof it a bit. |
112 | | |
113 | | // SAFETY: &T cast to *const T will always be aligned, initialised and valid for reads |
114 | 90.0k | let ptr = Arc::into_raw(unsafe { ptr::read(me) }); |
115 | 90.0k | let ptr = ptr as *mut T; |
116 | | |
117 | | // SAFETY: We got the pointer from into_raw just above |
118 | 90.0k | mem::forget(unsafe { Arc::from_raw(ptr) }); |
119 | | |
120 | 90.0k | ptr |
121 | 90.0k | } <alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>> as arc_swap::ref_cnt::RefCnt>::as_ptr Line | Count | Source | 97 | 2 | fn as_ptr(me: &Arc<T>) -> *mut T { | 98 | | // Slightly convoluted way to do this, but this avoids stacked borrows violations. The same | 99 | | // intention as | 100 | | // | 101 | | // me as &T as *const T as *mut T | 102 | | // | 103 | | // We first create a "shallow copy" of me - one that doesn't really own its ref count | 104 | | // (that's OK, me _does_ own it, so it can't be destroyed in the meantime). | 105 | | // Then we can use into_raw (which preserves not having the ref count). | 106 | | // | 107 | | // We need to "revert" the changes we did. In current std implementation, the combination | 108 | | // of from_raw and forget is no-op. But formally, into_raw shall be paired with from_raw | 109 | | // and that read shall be paired with forget to properly "close the brackets". In future | 110 | | // versions of STD, these may become something else that's not really no-op (unlikely, but | 111 | | // possible), so we future-proof it a bit. | 112 | | | 113 | | // SAFETY: &T cast to *const T will always be aligned, initialised and valid for reads | 114 | 2 | let ptr = Arc::into_raw(unsafe { ptr::read(me) }); | 115 | 2 | let ptr = ptr as *mut T; | 116 | | | 117 | | // SAFETY: We got the pointer from into_raw just above | 118 | 2 | mem::forget(unsafe { Arc::from_raw(ptr) }); | 119 | | | 120 | 2 | ptr | 121 | 2 | } |
Unexecuted instantiation: <alloc::sync::Arc<bytes::bytes::Bytes> as arc_swap::ref_cnt::RefCnt>::as_ptr <alloc::sync::Arc<(u64, std::time::Instant)> as arc_swap::ref_cnt::RefCnt>::as_ptr Line | Count | Source | 97 | 90.0k | fn as_ptr(me: &Arc<T>) -> *mut T { | 98 | | // Slightly convoluted way to do this, but this avoids stacked borrows violations. The same | 99 | | // intention as | 100 | | // | 101 | | // me as &T as *const T as *mut T | 102 | | // | 103 | | // We first create a "shallow copy" of me - one that doesn't really own its ref count | 104 | | // (that's OK, me _does_ own it, so it can't be destroyed in the meantime). | 105 | | // Then we can use into_raw (which preserves not having the ref count). | 106 | | // | 107 | | // We need to "revert" the changes we did. In current std implementation, the combination | 108 | | // of from_raw and forget is no-op. But formally, into_raw shall be paired with from_raw | 109 | | // and that read shall be paired with forget to properly "close the brackets". In future | 110 | | // versions of STD, these may become something else that's not really no-op (unlikely, but | 111 | | // possible), so we future-proof it a bit. | 112 | | | 113 | | // SAFETY: &T cast to *const T will always be aligned, initialised and valid for reads | 114 | 90.0k | let ptr = Arc::into_raw(unsafe { ptr::read(me) }); | 115 | 90.0k | let ptr = ptr as *mut T; | 116 | | | 117 | | // SAFETY: We got the pointer from into_raw just above | 118 | 90.0k | mem::forget(unsafe { Arc::from_raw(ptr) }); | 119 | | | 120 | 90.0k | ptr | 121 | 90.0k | } |
Unexecuted instantiation: <alloc::sync::Arc<_> as arc_swap::ref_cnt::RefCnt>::as_ptr |
122 | 52.5M | unsafe fn from_ptr(ptr: *const T) -> Arc<T> { |
123 | 52.5M | Arc::from_raw(ptr) |
124 | 52.5M | } <alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>> as arc_swap::ref_cnt::RefCnt>::from_ptr Line | Count | Source | 122 | 52.3M | unsafe fn from_ptr(ptr: *const T) -> Arc<T> { | 123 | 52.3M | Arc::from_raw(ptr) | 124 | 52.3M | } |
Unexecuted instantiation: <alloc::sync::Arc<bytes::bytes::Bytes> as arc_swap::ref_cnt::RefCnt>::from_ptr <alloc::sync::Arc<(u64, std::time::Instant)> as arc_swap::ref_cnt::RefCnt>::from_ptr Line | Count | Source | 122 | 195k | unsafe fn from_ptr(ptr: *const T) -> Arc<T> { | 123 | 195k | Arc::from_raw(ptr) | 124 | 195k | } |
Unexecuted instantiation: <alloc::sync::Arc<_> as arc_swap::ref_cnt::RefCnt>::from_ptr |
125 | | } |
126 | | |
127 | | unsafe impl<T> RefCnt for Rc<T> { |
128 | | type Base = T; |
129 | 0 | fn into_ptr(me: Rc<T>) -> *mut T { |
130 | 0 | Rc::into_raw(me) as *mut T |
131 | 0 | } |
132 | 0 | fn as_ptr(me: &Rc<T>) -> *mut T { |
133 | | // Slightly convoluted way to do this, but this avoids stacked borrows violations. The same |
134 | | // intention as |
135 | | // |
136 | | // me as &T as *const T as *mut T |
137 | | // |
138 | | // We first create a "shallow copy" of me - one that doesn't really own its ref count |
139 | | // (that's OK, me _does_ own it, so it can't be destroyed in the meantime). |
140 | | // Then we can use into_raw (which preserves not having the ref count). |
141 | | // |
142 | | // We need to "revert" the changes we did. In current std implementation, the combination |
143 | | // of from_raw and forget is no-op. But formally, into_raw shall be paired with from_raw |
144 | | // and that read shall be paired with forget to properly "close the brackets". In future |
145 | | // versions of STD, these may become something else that's not really no-op (unlikely, but |
146 | | // possible), so we future-proof it a bit. |
147 | | |
148 | | // SAFETY: &T cast to *const T will always be aligned, initialised and valid for reads |
149 | 0 | let ptr = Rc::into_raw(unsafe { ptr::read(me) }); |
150 | 0 | let ptr = ptr as *mut T; |
151 | | |
152 | | // SAFETY: We got the pointer from into_raw just above |
153 | 0 | mem::forget(unsafe { Rc::from_raw(ptr) }); |
154 | | |
155 | 0 | ptr |
156 | 0 | } |
157 | 0 | unsafe fn from_ptr(ptr: *const T) -> Rc<T> { |
158 | 0 | Rc::from_raw(ptr) |
159 | 0 | } |
160 | | } |
161 | | |
162 | | unsafe impl<T: RefCnt> RefCnt for Option<T> { |
163 | | type Base = T::Base; |
164 | 64.6M | fn into_ptr(me: Option<T>) -> *mut T::Base { |
165 | 64.6M | me.map(T::into_ptr).unwrap_or_else(ptr::null_mut) |
166 | 64.6M | } <core::option::Option<alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>>> as arc_swap::ref_cnt::RefCnt>::into_ptr Line | Count | Source | 164 | 64.6M | fn into_ptr(me: Option<T>) -> *mut T::Base { | 165 | 64.6M | me.map(T::into_ptr).unwrap_or_else(ptr::null_mut) | 166 | 64.6M | } |
Unexecuted instantiation: <core::option::Option<_> as arc_swap::ref_cnt::RefCnt>::into_ptr |
167 | 2 | fn as_ptr(me: &Option<T>) -> *mut T::Base { |
168 | 2 | me.as_ref().map(T::as_ptr).unwrap_or_else(ptr::null_mut) |
169 | 2 | } <core::option::Option<alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>>> as arc_swap::ref_cnt::RefCnt>::as_ptr Line | Count | Source | 167 | 2 | fn as_ptr(me: &Option<T>) -> *mut T::Base { | 168 | 2 | me.as_ref().map(T::as_ptr).unwrap_or_else(ptr::null_mut) | 169 | 2 | } |
Unexecuted instantiation: <core::option::Option<_> as arc_swap::ref_cnt::RefCnt>::as_ptr |
170 | 64.6M | unsafe fn from_ptr(ptr: *const T::Base) -> Option<T> { |
171 | 64.6M | if ptr.is_null() { |
172 | 12.2M | None |
173 | | } else { |
174 | 52.3M | Some(T::from_ptr(ptr)) |
175 | | } |
176 | 64.6M | } <core::option::Option<alloc::sync::Arc<crossbeam_deque::deque::Stealer<async_task::runnable::Runnable>>> as arc_swap::ref_cnt::RefCnt>::from_ptr Line | Count | Source | 170 | 64.6M | unsafe fn from_ptr(ptr: *const T::Base) -> Option<T> { | 171 | 64.6M | if ptr.is_null() { | 172 | 12.2M | None | 173 | | } else { | 174 | 52.3M | Some(T::from_ptr(ptr)) | 175 | | } | 176 | 64.6M | } |
Unexecuted instantiation: <core::option::Option<_> as arc_swap::ref_cnt::RefCnt>::from_ptr |
177 | | } |
178 | | |
179 | | // Pin is only available since Rust 1.33, but Pin::into_inner is from 1.39. |
180 | | #[rustversion::since(1.39)] |
181 | | unsafe impl<T> RefCnt for Pin<Arc<T>> { |
182 | | type Base = T; |
183 | | |
184 | 0 | fn into_ptr(me: Pin<Arc<T>>) -> *mut T { |
185 | | // SAFETY: We only expose an opaque pointer, which maintains the `Pin` invariant. |
186 | 0 | Arc::into_raw(unsafe { Pin::into_inner_unchecked(me) }) as *mut T |
187 | 0 | } |
188 | | |
189 | 0 | fn as_ptr(me: &Pin<Arc<T>>) -> *mut T { |
190 | | // Slightly convoluted way to do this, but this avoids stacked borrows violations. The same |
191 | | // intention as |
192 | | // |
193 | | // me as &T as *const T as *mut T |
194 | | // |
195 | | // We first create a "shallow copy" of me - one that doesn't really own its ref count |
196 | | // (that's OK, me _does_ own it, so it can't be destroyed in the meantime). |
197 | | // Then we can use into_raw (which preserves not having the ref count). |
198 | | // |
199 | | // We need to "revert" the changes we did. In current std implementation, the combination |
200 | | // of from_raw and forget is no-op. But formally, into_raw shall be paired with from_raw |
201 | | // and that read shall be paired with forget to properly "close the brackets". In future |
202 | | // versions of STD, these may become something else that's not really no-op (unlikely, but |
203 | | // possible), so we future-proof it a bit. |
204 | | |
205 | | // SAFETY: &T cast to *const T will always be aligned, initialised and valid for reads |
206 | | // We only expose an opaque pointer, which maintains the `Pin` invariant. |
207 | 0 | let me = Arc::into_raw(unsafe { Pin::into_inner_unchecked(ptr::read(me)) }); |
208 | 0 | let ptr = me as *mut T; |
209 | | |
210 | | // SAFETY: We got the pointer from into_raw just above |
211 | 0 | mem::forget(unsafe { Arc::from_raw(ptr) }); |
212 | | |
213 | 0 | ptr |
214 | 0 | } |
215 | | |
216 | 0 | unsafe fn from_ptr(ptr: *const T) -> Self { |
217 | | // SAFETY: `ptr` came from a previous `{into_ptr,as_ptr}` call, which is pinned. |
218 | 0 | unsafe { Pin::new_unchecked(Arc::from_raw(ptr)) } |
219 | 0 | } |
220 | | } |
221 | | |
222 | | // Pin is only available since Rust 1.33, but Pin::into_inner is from 1.39. |
223 | | #[rustversion::since(1.39)] |
224 | | unsafe impl<T> RefCnt for Pin<Rc<T>> { |
225 | | type Base = T; |
226 | | |
227 | 0 | fn into_ptr(me: Pin<Rc<T>>) -> *mut T { |
228 | | // SAFETY: We only expose an opaque pointer, which maintains the `Pin` invariant. |
229 | 0 | Rc::into_raw(unsafe { Pin::into_inner_unchecked(me) }) as *mut T |
230 | 0 | } |
231 | | |
232 | 0 | fn as_ptr(me: &Pin<Rc<T>>) -> *mut T { |
233 | | // Slightly convoluted way to do this, but this avoids stacked borrows violations. The same |
234 | | // intention as |
235 | | // |
236 | | // me as &T as *const T as *mut T |
237 | | // |
238 | | // We first create a "shallow copy" of me - one that doesn't really own its ref count |
239 | | // (that's OK, me _does_ own it, so it can't be destroyed in the meantime). |
240 | | // Then we can use into_raw (which preserves not having the ref count). |
241 | | // |
242 | | // We need to "revert" the changes we did. In current std implementation, the combination |
243 | | // of from_raw and forget is no-op. But formally, into_raw shall be paired with from_raw |
244 | | // and that read shall be paired with forget to properly "close the brackets". In future |
245 | | // versions of STD, these may become something else that's not really no-op (unlikely, but |
246 | | // possible), so we future-proof it a bit. |
247 | | |
248 | | // SAFETY: &T cast to *const T will always be aligned, initialised and valid for reads |
249 | | // We only expose an opaque pointer, which maintains the `Pin` invariant. |
250 | 0 | let me = Rc::into_raw(unsafe { Pin::into_inner_unchecked(ptr::read(me)) }); |
251 | 0 | let ptr = me as *mut T; |
252 | | |
253 | | // SAFETY: We got the pointer from into_raw just above |
254 | 0 | mem::forget(unsafe { Rc::from_raw(ptr) }); |
255 | | |
256 | 0 | ptr |
257 | 0 | } |
258 | | |
259 | 0 | unsafe fn from_ptr(ptr: *const T) -> Self { |
260 | | // SAFETY: `ptr` came from a previous `{into_ptr,as_ptr}` call, which is pinned. |
261 | 0 | unsafe { Pin::new_unchecked(Rc::from_raw(ptr)) } |
262 | 0 | } |
263 | | } |
264 | | |
265 | | #[cfg(test)] |
266 | | mod tests { |
267 | | use super::*; |
268 | | |
269 | | #[test] |
270 | | fn ref_cnt_arc() { |
271 | | struct Data(u32); |
272 | | |
273 | | let arc = Arc::new(Data(114514)); |
274 | | let ptr = RefCnt::as_ptr(&arc); |
275 | | assert_eq!(ptr, RefCnt::into_ptr(arc)); |
276 | | |
277 | | let arc: Arc<Data> = unsafe { RefCnt::from_ptr(ptr) }; |
278 | | assert_eq!(arc.0, 114514); |
279 | | assert_eq!(ptr, RefCnt::as_ptr(&arc)); |
280 | | assert_eq!(ptr, RefCnt::into_ptr(arc)); |
281 | | |
282 | | // Let it drop. |
283 | | let _: Arc<Data> = unsafe { RefCnt::from_ptr(ptr) }; |
284 | | } |
285 | | |
286 | | // Pin is only available since Rust 1.33, but Pin::into_inner is from 1.39. |
287 | | #[rustversion::since(1.39)] |
288 | | mod pin { |
289 | | use super::*; |
290 | | use core::marker::PhantomPinned; |
291 | | |
292 | | #[test] |
293 | | fn ref_cnt_pin_arc() { |
294 | | struct Unmovable { |
295 | | value: u32, |
296 | | _phantom: PhantomPinned, |
297 | | } |
298 | | |
299 | | let pinned = Arc::pin(Unmovable { |
300 | | value: 114514, |
301 | | _phantom: PhantomPinned, |
302 | | }); |
303 | | let ptr = RefCnt::as_ptr(&pinned); |
304 | | assert_eq!(ptr, RefCnt::into_ptr(pinned)); |
305 | | |
306 | | let pinned: Pin<Arc<Unmovable>> = unsafe { RefCnt::from_ptr(ptr) }; |
307 | | assert_eq!(pinned.value, 114514); |
308 | | assert_eq!(ptr, RefCnt::as_ptr(&pinned)); |
309 | | assert_eq!(ptr, RefCnt::into_ptr(pinned)); |
310 | | |
311 | | // Let it drop. |
312 | | let _: Pin<Arc<Unmovable>> = unsafe { RefCnt::from_ptr(ptr) }; |
313 | | } |
314 | | |
315 | | #[test] |
316 | | fn ref_cnt_pin_rc() { |
317 | | struct Unmovable { |
318 | | value: u32, |
319 | | _phantom: PhantomPinned, |
320 | | } |
321 | | |
322 | | let pinned = Rc::pin(Unmovable { |
323 | | value: 114514, |
324 | | _phantom: PhantomPinned, |
325 | | }); |
326 | | let ptr = RefCnt::as_ptr(&pinned); |
327 | | assert_eq!(ptr, RefCnt::into_ptr(pinned)); |
328 | | |
329 | | let pinned: Pin<Rc<Unmovable>> = unsafe { RefCnt::from_ptr(ptr) }; |
330 | | assert_eq!(pinned.value, 114514); |
331 | | assert_eq!(ptr, RefCnt::as_ptr(&pinned)); |
332 | | assert_eq!(ptr, RefCnt::into_ptr(pinned)); |
333 | | |
334 | | // Let it drop. |
335 | | let _: Pin<Rc<Unmovable>> = unsafe { RefCnt::from_ptr(ptr) }; |
336 | | } |
337 | | } |
338 | | } |