mco 0.1.48

Rust Coroutine Library like go
Documentation
use crossbeam_utils::atomic::AtomicCell;
use std::borrow::Borrow;
use std::fmt::{Debug, Formatter};

pub struct AtomicOption<T> {
    inner: AtomicCell<Option<T>>,
}

impl<T: std::fmt::Debug> Debug for AtomicOption<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self.get() {
            None => f
                .debug_struct("AtomicOption")
                .field("inner", &Option::<T>::None)
                .finish(),
            Some(s) => f.debug_struct("AtomicOption").field("inner", s).finish(),
        }
    }
}

unsafe impl<T> Send for AtomicOption<T> {}

unsafe impl<T> Sync for AtomicOption<T> {}

impl<T> AtomicOption<T> {
    pub fn none() -> AtomicOption<T> {
        AtomicOption {
            inner: AtomicCell::new(None),
        }
    }

    pub fn some(t: T) -> AtomicOption<T> {
        AtomicOption {
            inner: AtomicCell::new(Some(t)),
        }
    }

    #[inline]
    pub fn store(&self, t: T) {
        self.inner.store(Some(t))
    }

    #[inline]
    pub fn swap(&self, t: T) -> Option<T> {
        self.inner.swap(Some(t))
    }

    #[inline]
    pub fn take(&self) -> Option<T> {
        self.inner.take()
    }

    #[inline]
    pub fn is_none(&self) -> bool {
        unsafe { (&(*self.inner.borrow().as_ptr())).is_none() }
    }

    #[inline]
    pub fn is_some(&self) -> bool {
        unsafe { (&(*self.inner.borrow().as_ptr())).is_some() }
    }

    #[inline]
    pub fn get(&self) -> Option<&T> {
        match unsafe { &(*self.inner.borrow().as_ptr()) } {
            None => None,
            Some(v) => Some(v),
        }
    }
}

impl<T> Default for AtomicOption<T> {
    fn default() -> Self {
        Self::none()
    }
}

impl<T> Drop for AtomicOption<T> {
    fn drop(&mut self) {
        self.inner.store(None)
    }
}