alopt 0.1.0

a Rust crate providing efficient synchronization primitives that integrate Option into their design.
Documentation
use super::{Wom, Worl};

use std::sync::atomic::Ordering::*;

pub struct WorlGuardRead<'a, T: 'a> {
    worl: &'a Worl<T>,
}

pub struct WorlGuardWrite<'a, T: 'a> {
    worl: &'a Worl<T>,
}

pub struct WomGuard<'a, T: 'a> {
    wom: &'a Wom<T>,
}

impl<'a, T: 'a> WorlGuardRead<'a, T> {
    pub(super) fn new(worl: &'a Worl<T>) -> Self {
        Self { worl }
    }
}

impl<'a, T: 'a> WorlGuardWrite<'a, T> {
    pub(super) fn new(worl: &'a Worl<T>) -> Self {
        Self { worl }
    }
}

impl<'a, T: 'a> WomGuard<'a, T> {
    pub(super) fn new(wom: &'a Wom<T>) -> Self {
        Self { wom }
    }
}

impl<'a, T: 'a> std::ops::Deref for WorlGuardRead<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        let data_outer = unsafe { &*self.worl.data.get() };
        data_outer.as_ref().unwrap()
    }
}

impl<'a, T: 'a> std::ops::Deref for WorlGuardWrite<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        let data_outer = unsafe { &*self.worl.data.get() };
        data_outer.as_ref().unwrap()
    }
}

impl<'a, T: 'a> std::ops::DerefMut for WorlGuardWrite<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let data_outer = unsafe { &mut *self.worl.data.get() };
        data_outer.as_mut().unwrap()
    }
}

impl<'a, T: 'a> Drop for WorlGuardRead<'a, T> {
    fn drop(&mut self) {
        self.worl.sem.release_read();
    }
}

impl<'a, T: 'a> Drop for WorlGuardWrite<'a, T> {
    fn drop(&mut self) {
        self.worl.sem.release_write();
    }
}

impl<'a, T: 'a> std::ops::Deref for WomGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        if self.wom.mtx.fetch_add(1, Release) < 0 {
            panic!(
                "cannot access an immutable reference of Wom while there is an active mutable reference!"
            );
        }
        self.wom.get_ref().unwrap()
    }
}

impl<'a, T: 'a> std::ops::DerefMut for WomGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let accesses = self.wom.mtx.fetch_sub(1, Release);
        match accesses.cmp(&0) {
            std::cmp::Ordering::Less => {
                panic!("cannot access a mutable reference of Wom more than once at a time!")
            }
            std::cmp::Ordering::Greater => panic!(
                "cannot access a mutable reference of Wom while there are active immutable references!"
            ),
            _ => (),
        }
        self.wom.get_ref().unwrap()
    }
}

impl<'a, T: 'a> Drop for WomGuard<'a, T> {
    fn drop(&mut self) {
        if self.wom.mtx.load(Acquire) < 0 {
            self.wom.mtx.fetch_add(1, Release);
        } else {
            self.wom.mtx.fetch_sub(1, Release);
        }
    }
}