use crate::loom::sync::atomic::AtomicPtr; use std::ptr; use std::sync::atomic::Ordering::AcqRel; pub(super) struct AtomicCell { data: AtomicPtr, } unsafe impl Send for AtomicCell {} unsafe impl Sync for AtomicCell {} impl AtomicCell { pub(super) fn new(data: Option>) -> AtomicCell { AtomicCell { data: AtomicPtr::new(to_raw(data)), } } pub(super) fn swap(&self, val: Option>) -> Option> { let old = self.data.swap(to_raw(val), AcqRel); from_raw(old) } #[cfg(feature = "blocking")] pub(super) fn set(&self, val: Box) { let _ = self.swap(Some(val)); } pub(super) fn take(&self) -> Option> { self.swap(None) } } fn to_raw(data: Option>) -> *mut T { data.map(Box::into_raw).unwrap_or(ptr::null_mut()) } fn from_raw(val: *mut T) -> Option> { if val.is_null() { None } else { Some(unsafe { Box::from_raw(val) }) } } impl Drop for AtomicCell { fn drop(&mut self) { // Free any data still held by the cell let _ = self.take(); } }