postage 0.5.0

An async channel library
Documentation
use std::cell::UnsafeCell;

use atomic::{Atomic, Ordering};

pub struct StateCell<S, T>
where
    S: Copy,
{
    state: Atomic<S>,
    data: UnsafeCell<Option<T>>,
}

impl<S, T> StateCell<S, T>
where
    S: Copy,
{
    pub fn new(state: S) -> Self {
        debug_assert!(Atomic::<S>::is_lock_free());

        Self {
            state: Atomic::new(state),
            data: UnsafeCell::new(None),
        }
    }

    pub unsafe fn compare_store(
        &self,
        current: S,
        locked: S,
        data: T,
        complete: S,
        success: Ordering,
        failure: Ordering,
    ) -> Result<S, (S, T)> {
        match self
            .state
            .compare_exchange(current, locked, success, failure)
        {
            Ok(s) => {
                *self.data.get() = Some(data);
                self.state.store(complete, Ordering::Release);
                Ok(s)
            }
            Err(s) => Err((s, data)),
        }
    }

    pub unsafe fn compare_take(
        &self,
        current: S,
        new: S,
        success: Ordering,
        failure: Ordering,
    ) -> Result<T, S> {
        match self.state.compare_exchange(current, new, success, failure) {
            Ok(_s) => Ok(self.take_internal()),
            Err(s) => Err(s),
        }
    }

    unsafe fn take_internal(&self) -> T {
        let reference = self.data.get().as_mut().unwrap();
        reference.take().unwrap()
    }
}

unsafe impl<S, T> Sync for StateCell<S, T>
where
    S: Copy,
    T: Send,
{
}