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