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 T34 fn 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>>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> {
drop(&mut self)47     fn drop(&mut self) {
48         // Free any data still held by the cell
49         let _ = self.take();
50     }
51 }
52