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