1 use crate::loom::sync::atomic::AtomicPtr; 2 3 use std::ptr; 4 use std::sync::atomic::Ordering::AcqRel; 5 6 pub(super) struct AtomicCell<T> { 7 data: AtomicPtr<T>, 8 } 9 10 unsafe impl<T: Send> Send for AtomicCell<T> {} 11 unsafe impl<T: Send> Sync for AtomicCell<T> {} 12 13 impl<T> AtomicCell<T> { new(data: Option<Box<T>>) -> AtomicCell<T>14 pub(super) fn new(data: Option<Box<T>>) -> AtomicCell<T> { 15 AtomicCell { 16 data: AtomicPtr::new(to_raw(data)), 17 } 18 } 19 swap(&self, val: Option<Box<T>>) -> Option<Box<T>>20 pub(super) fn swap(&self, val: Option<Box<T>>) -> Option<Box<T>> { 21 let old = self.data.swap(to_raw(val), AcqRel); 22 from_raw(old) 23 } 24 set(&self, val: Box<T>)25 pub(super) fn set(&self, val: Box<T>) { 26 let _ = self.swap(Some(val)); 27 } 28 take(&self) -> Option<Box<T>>29 pub(super) fn take(&self) -> Option<Box<T>> { 30 self.swap(None) 31 } 32 } 33 to_raw<T>(data: Option<Box<T>>) -> *mut T34fn to_raw<T>(data: Option<Box<T>>) -> *mut T { 35 data.map(Box::into_raw).unwrap_or(ptr::null_mut()) 36 } 37 from_raw<T>(val: *mut T) -> Option<Box<T>>38fn from_raw<T>(val: *mut T) -> Option<Box<T>> { 39 if val.is_null() { 40 None 41 } else { 42 Some(unsafe { Box::from_raw(val) }) 43 } 44 } 45 46 impl<T> Drop for AtomicCell<T> { drop(&mut self)47 fn drop(&mut self) { 48 // Free any data still held by the cell 49 let _ = self.take(); 50 } 51 } 52