| 1 | use crate::loom::sync::atomic::AtomicPtr; |
| 2 | |
| 3 | use std::ptr; |
| 4 | use std::sync::atomic::Ordering::AcqRel; |
| 5 | |
| 6 | pub(crate) 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> { |
| 14 | pub(crate) fn new(data: Option<Box<T>>) -> AtomicCell<T> { |
| 15 | AtomicCell { |
| 16 | data: AtomicPtr::new(to_raw(data)), |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | pub(crate) fn swap(&self, val: Option<Box<T>>) -> Option<Box<T>> { |
| 21 | let old: *mut T = self.data.swap(ptr:to_raw(val), order:AcqRel); |
| 22 | from_raw(val:old) |
| 23 | } |
| 24 | |
| 25 | pub(crate) fn set(&self, val: Box<T>) { |
| 26 | let _ = self.swap(val:Some(val)); |
| 27 | } |
| 28 | |
| 29 | pub(crate) fn take(&self) -> Option<Box<T>> { |
| 30 | self.swap(val:None) |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | fn to_raw<T>(data: Option<Box<T>>) -> *mut T { |
| 35 | data.map_or(default:ptr::null_mut(), f:Box::into_raw) |
| 36 | } |
| 37 | |
| 38 | fn 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> { |
| 47 | fn drop(&mut self) { |
| 48 | // Free any data still held by the cell |
| 49 | let _ = self.take(); |
| 50 | } |
| 51 | } |
| 52 | |