alopt 1.0.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 {
        unsafe { &*self.worl.data.as_ref().unwrap().get() }
    }
}

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

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

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

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!"
            );
        }
        unsafe { &*self.wom.data.as_ref().unwrap().get() }
    }
}

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);
        if accesses < 0 {
            panic!("cannot access a mutable reference of Wom more than once at a time!");
        } else if accesses > 0 {
            panic!(
                "cannot access a mutable reference of Wom while there are active immutable references!"
            );
        }
        unsafe { &mut *self.wom.data.as_ref().unwrap().get() }
    }
}

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);
        }
    }
}