use std::ptr; use std::rc::Weak as RcWeak; use std::sync::Weak; use crate::RefCnt; unsafe impl RefCnt for Weak { type Base = T; fn as_ptr(me: &Self) -> *mut T { if Weak::ptr_eq(&Weak::new(), me) { ptr::null_mut() } else { Weak::as_ptr(me) as *mut T } } fn into_ptr(me: Self) -> *mut T { if Weak::ptr_eq(&Weak::new(), &me) { ptr::null_mut() } else { Weak::into_raw(me) as *mut T } } unsafe fn from_ptr(ptr: *const T) -> Self { if ptr.is_null() { Weak::new() } else { Weak::from_raw(ptr) } } } unsafe impl RefCnt for RcWeak { type Base = T; fn as_ptr(me: &Self) -> *mut T { if RcWeak::ptr_eq(&RcWeak::new(), me) { ptr::null_mut() } else { RcWeak::as_ptr(me) as *mut T } } fn into_ptr(me: Self) -> *mut T { if RcWeak::ptr_eq(&RcWeak::new(), &me) { ptr::null_mut() } else { RcWeak::into_raw(me) as *mut T } } unsafe fn from_ptr(ptr: *const T) -> Self { if ptr.is_null() { RcWeak::new() } else { RcWeak::from_raw(ptr) } } } macro_rules! t { ($name: ident, $strategy: ty) => { #[cfg(test)] mod $name { use std::sync::{Arc, Weak}; use crate::ArcSwapAny; #[allow(deprecated)] // We use "deprecated" testing strategies in here. type ArcSwapWeak = ArcSwapAny, $strategy>; // Convert to weak, push it through the shared and pull it out again. #[test] fn there_and_back() { let data = Arc::new("Hello"); let shared = ArcSwapWeak::new(Arc::downgrade(&data)); assert_eq!(1, Arc::strong_count(&data)); assert_eq!(1, Arc::weak_count(&data)); let weak = shared.load(); assert_eq!("Hello", *weak.upgrade().unwrap()); assert!(Arc::ptr_eq(&data, &weak.upgrade().unwrap())); } // Replace a weak pointer with a NULL one #[test] fn reset() { let data = Arc::new("Hello"); let shared = ArcSwapWeak::new(Arc::downgrade(&data)); assert_eq!(1, Arc::strong_count(&data)); assert_eq!(1, Arc::weak_count(&data)); // An empty weak (eg. NULL) shared.store(Weak::new()); assert_eq!(1, Arc::strong_count(&data)); assert_eq!(0, Arc::weak_count(&data)); let weak = shared.load(); assert!(weak.upgrade().is_none()); } // Destroy the underlying data while the weak is still stored inside. Should make it go // NULL-ish #[test] fn destroy() { let data = Arc::new("Hello"); let shared = ArcSwapWeak::new(Arc::downgrade(&data)); drop(data); let weak = shared.load(); assert!(weak.upgrade().is_none()); } } }; } t!(tests_default, crate::DefaultStrategy); #[cfg(feature = "internal-test-strategies")] t!( tests_full_slots, crate::strategy::test_strategies::FillFastSlots );