arc_swap/
weak.rs

1use core::ptr;
2
3use alloc::rc::Weak as RcWeak;
4use alloc::sync::Weak;
5
6use crate::RefCnt;
7
8unsafe impl<T> RefCnt for Weak<T> {
9    type Base = T;
10    fn as_ptr(me: &Self) -> *mut T {
11        if Weak::ptr_eq(&Weak::new(), me) {
12            ptr::null_mut()
13        } else {
14            Weak::as_ptr(me) as *mut T
15        }
16    }
17    fn into_ptr(me: Self) -> *mut T {
18        if Weak::ptr_eq(&Weak::new(), &me) {
19            ptr::null_mut()
20        } else {
21            Weak::into_raw(me) as *mut T
22        }
23    }
24    unsafe fn from_ptr(ptr: *const T) -> Self {
25        if ptr.is_null() {
26            Weak::new()
27        } else {
28            Weak::from_raw(ptr)
29        }
30    }
31}
32
33unsafe impl<T> RefCnt for RcWeak<T> {
34    type Base = T;
35    fn as_ptr(me: &Self) -> *mut T {
36        if RcWeak::ptr_eq(&RcWeak::new(), me) {
37            ptr::null_mut()
38        } else {
39            RcWeak::as_ptr(me) as *mut T
40        }
41    }
42    fn into_ptr(me: Self) -> *mut T {
43        if RcWeak::ptr_eq(&RcWeak::new(), &me) {
44            ptr::null_mut()
45        } else {
46            RcWeak::into_raw(me) as *mut T
47        }
48    }
49    unsafe fn from_ptr(ptr: *const T) -> Self {
50        if ptr.is_null() {
51            RcWeak::new()
52        } else {
53            RcWeak::from_raw(ptr)
54        }
55    }
56}
57
58macro_rules! t {
59    ($name: ident, $strategy: ty) => {
60        #[cfg(test)]
61        mod $name {
62            use alloc::sync::{Arc, Weak};
63
64            use crate::ArcSwapAny;
65
66            #[allow(deprecated)] // We use "deprecated" testing strategies in here.
67            type ArcSwapWeak<T> = ArcSwapAny<Weak<T>, $strategy>;
68
69            // Convert to weak, push it through the shared and pull it out again.
70            #[test]
71            fn there_and_back() {
72                let data = Arc::new("Hello");
73                let shared = ArcSwapWeak::new(Arc::downgrade(&data));
74                assert_eq!(1, Arc::strong_count(&data));
75                assert_eq!(1, Arc::weak_count(&data));
76                let weak = shared.load();
77                assert_eq!("Hello", *weak.upgrade().unwrap());
78                assert!(Arc::ptr_eq(&data, &weak.upgrade().unwrap()));
79            }
80
81            // Replace a weak pointer with a NULL one
82            #[test]
83            fn reset() {
84                let data = Arc::new("Hello");
85                let shared = ArcSwapWeak::new(Arc::downgrade(&data));
86                assert_eq!(1, Arc::strong_count(&data));
87                assert_eq!(1, Arc::weak_count(&data));
88
89                // An empty weak (eg. NULL)
90                shared.store(Weak::new());
91                assert_eq!(1, Arc::strong_count(&data));
92                assert_eq!(0, Arc::weak_count(&data));
93
94                let weak = shared.load();
95                assert!(weak.upgrade().is_none());
96            }
97
98            // Destroy the underlying data while the weak is still stored inside. Should make it go
99            // NULL-ish
100            #[test]
101            fn destroy() {
102                let data = Arc::new("Hello");
103                let shared = ArcSwapWeak::new(Arc::downgrade(&data));
104
105                drop(data);
106                let weak = shared.load();
107                assert!(weak.upgrade().is_none());
108            }
109        }
110    };
111}
112
113t!(tests_default, crate::DefaultStrategy);
114#[cfg(feature = "internal-test-strategies")]
115t!(
116    tests_full_slots,
117    crate::strategy::test_strategies::FillFastSlots
118);