fibers 0.1.13

A Rust library to execute a number of lightweight asynchronous tasks (a.k.a, fibers) based on futures and mio
Documentation
// Copyright (c) 2016 DWANGO Co., Ltd. All Rights Reserved.
// See the LICENSE file at the top-level directory of this distribution.

#![allow(dead_code)]
use std::ops;
use std::ptr;
use std::sync::atomic::{self, AtomicPtr};

#[derive(Debug)]
pub struct AtomicCell<T> {
    inner: AtomicPtr<T>,
}
impl<T> AtomicCell<T> {
    pub fn new(inner: T) -> Self {
        let boxed = Box::new(inner);
        AtomicCell {
            inner: AtomicPtr::new(Box::into_raw(boxed)),
        }
    }
    pub fn try_borrow_mut(&self) -> Option<AtomicBorrowMut<T>> {
        let old = self.inner.swap(ptr::null_mut(), atomic::Ordering::SeqCst);
        if old.is_null() {
            None
        } else {
            let inner = unsafe { Box::from_raw(old) };
            Some(AtomicBorrowMut::new(self, inner))
        }
    }
    pub fn try_borrow(&self) -> Option<AtomicBorrowRef<T>> {
        self.try_borrow_mut().map(AtomicBorrowRef)
    }
}
impl<T> Drop for AtomicCell<T> {
    fn drop(&mut self) {
        let inner = self.inner.load(atomic::Ordering::SeqCst);
        assert_ne!(inner, ptr::null_mut());
        let _ = unsafe { Box::from_raw(inner) };
    }
}

pub struct AtomicBorrowMut<'a, T: 'a> {
    owner: &'a AtomicCell<T>,
    inner: Option<Box<T>>,
}
impl<'a, T> AtomicBorrowMut<'a, T> {
    fn new(owner: &'a AtomicCell<T>, inner: Box<T>) -> Self {
        AtomicBorrowMut {
            owner,
            inner: Some(inner),
        }
    }
}
impl<'a, T> ops::Deref for AtomicBorrowMut<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        &*assert_some!(self.inner.as_ref())
    }
}
impl<'a, T> ops::DerefMut for AtomicBorrowMut<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut *assert_some!(self.inner.as_mut())
    }
}
impl<'a, T> Drop for AtomicBorrowMut<'a, T> {
    fn drop(&mut self) {
        let inner = Box::into_raw(assert_some!(self.inner.take()));
        let old = self.owner.inner.swap(inner, atomic::Ordering::SeqCst);
        assert_eq!(old, ptr::null_mut());
    }
}

pub struct AtomicBorrowRef<'a, T: 'a>(AtomicBorrowMut<'a, T>);
impl<'a, T> ops::Deref for AtomicBorrowRef<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.0
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn it_works() {
        let x = AtomicCell::new(10);
        {
            let y = x.try_borrow_mut();
            assert!(y.is_some());
            let mut y = y.unwrap();
            assert_eq!(*y, 10);

            let z = x.try_borrow_mut();
            assert!(z.is_none());

            *y = 20;
        }
        let z = x.try_borrow_mut();
        assert!(z.is_some());
        assert_eq!(*z.unwrap(), 20);
    }
}