use alloc::sync::Arc; use core::{ fmt::{self, Debug, Formatter}, ptr::NonNull, sync::atomic::{AtomicPtr, Ordering}, }; use pointers::BorrowedArc; unsafe impl Send for ArcSwap where T: Send + Sync {} unsafe impl Sync for ArcSwap where T: Send + Sync {} pub struct ArcSwap { pointer: AtomicPtr, } impl ArcSwap { pub fn new(data: T) -> Self { let pointer = Arc::into_raw(Arc::new(data)); Self { pointer: AtomicPtr::new(pointer as *mut T), } } /// # Safety /// The caller must ensure that the pointer not used elsewhere before ACTUALLLY dropping that. pub fn swap(&self, data: Option>) -> Option> { let new_pointer = data.map(Arc::into_raw).unwrap_or(core::ptr::null()); let old_pointer = self.pointer.swap(new_pointer as *mut _, Ordering::AcqRel); if old_pointer.is_null() { None } else { Some(unsafe { Arc::from_raw(old_pointer) }) } } pub fn borrow(&self) -> BorrowedArc { unsafe { BorrowedArc::from_raw( NonNull::new(self.pointer.load(Ordering::Acquire)) .expect("ArcSwap: pointer should not be null."), ) } } } impl Debug for ArcSwap where T: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "ArcSwap {{ {:?} }}", self.borrow().as_ref()) } }