rw-cell 2.0.3

Write data to cell from anything place your application without copy, lock and reading in one place
Documentation
use std::sync::atomic::{AtomicPtr, Ordering};

pub struct OptionCell<T> {
    inner: AtomicPtr<Option<T>>
}

impl<T> OptionCell<T> {
    pub fn new(val: T) -> Self {
        Self {
            inner: AtomicPtr::new(some_raw_ptr(val)),
        }
    }

    pub fn replace(&self, val: T) -> Option<T> {
        let val_ptr = Box::into_raw(Box::new(Some(val)));
        let old_val_ptr = self.inner.swap(val_ptr, Ordering::SeqCst);
        *unsafe { Box::from_raw(old_val_ptr) }
    }

    pub fn take(&self) -> Option<T> {
        let curr_val = self.inner.swap(none_raw_ptr(), Ordering::SeqCst);
        *unsafe { Box::from_raw(curr_val) }
    }
}

impl<T> Drop for OptionCell<T> {
    fn drop(&mut self) {
        let _ = unsafe { Box::from_raw(self.inner.load(Ordering::SeqCst)) };
    }
}

impl<T> Default for OptionCell<T> {
    fn default() -> Self {
        Self { inner: AtomicPtr::new(none_raw_ptr()) }
    }
}

#[inline]
pub(crate) fn none_raw_ptr<T>() -> *mut Option<T> {
    Box::into_raw(Box::new(None))
}

#[inline]
pub(crate) fn some_raw_ptr<T>(val: T) -> *mut Option<T> {
    Box::into_raw(Box::new(Some(val)))
}

#[cfg(test)]
mod tests {
    use crate::option::OptionCell;

    #[test]
    fn test_option_cell_new() {
        let cell = OptionCell::new("aa");
        assert_eq!(Some("aa"), cell.take());
        assert_eq!(None, cell.replace("bb"));
        assert_eq!(Some("bb"), cell.take());
    }
    #[test]
    fn test_option_cell_default() {
        let cell = OptionCell::default();
        assert_eq!(None, cell.replace("bb"));
        assert_eq!(Some("bb"), cell.take());
    }
}