anode 0.1.0

Concurrency library for Rust.
Documentation
use std::time::Duration;
use crate::deadline::Deadline;
use crate::monitor::{Directive, Monitor, SpeculativeMonitor};
use crate::xlock::{Moderator};

#[derive(Debug)]
pub struct WriteBiased;

pub struct WriteBiasedSync {
    monitor: SpeculativeMonitor<WriteBiasedState>,
}

#[derive(Debug)]
struct WriteBiasedState {
    readers: u32,
    writer: bool,
    writer_pending: bool,
}

impl Moderator for WriteBiased {
    type Sync = WriteBiasedSync;

    #[inline]
    fn new() -> Self::Sync {
        Self::Sync {
            monitor: SpeculativeMonitor::new(WriteBiasedState { readers: 0, writer: false, writer_pending: false }),
        }
    }

    #[inline]
    fn try_read(sync: &Self::Sync, duration: Duration) -> bool {
        let mut deadline = Deadline::lazy_after(duration);
        let mut acquired = false;
        let mut saw_no_pending_writer = false;
        sync.monitor.enter(|state| {
            if !state.writer_pending {
                saw_no_pending_writer = true;
            }

            if !acquired && !state.writer && saw_no_pending_writer {
                acquired = true;
                state.readers += 1;
            }

            if acquired {
                Directive::Return
            } else {
                Directive::Wait(deadline.remaining())
            }
        });
        acquired
    }

    #[inline]
    fn read_unlock(sync: &Self::Sync) {
        let mut released = false;
        sync.monitor.enter(|state| {
            if !released {
                debug_assert!(state.readers > 0, "readers: {}", state.readers);
                debug_assert!(!state.writer);

                released = true;
                state.readers -= 1;
            }

            match state.readers {
                0 | 1 => Directive::NotifyAll,
                _ => Directive::Return
            }
        });
    }

    #[inline]
    fn try_write(sync: &Self::Sync, duration: Duration) -> bool {
        let mut deadline = Deadline::lazy_after(duration);
        let mut acquired = false;
        let mut self_writer_pending = false;
        sync.monitor.enter(|state| {
            if !acquired {
                if state.readers == 0 && !state.writer {
                    state.writer = true;
                    acquired = true;
                } else if !state.writer_pending {
                    self_writer_pending = true;
                    state.writer_pending = true;
                }
            }

            if acquired {
                Directive::Return
            } else {
                Directive::Wait(deadline.remaining())
            }
        });

        if self_writer_pending {
            let mut cleared_writer_pending = false;
            sync.monitor.enter(|state| {
                if !cleared_writer_pending {
                    cleared_writer_pending = true;
                    state.writer_pending = false;
                }

                if acquired {
                    Directive::Return
                } else {
                    Directive::NotifyAll
                }
            });
        }

        acquired
    }

    #[inline]
    fn write_unlock(sync: &Self::Sync) {
        let mut released = false;
        sync.monitor.enter(|state| {
            if !released {
                debug_assert!(state.readers == 0, "readers: {}", state.readers);
                debug_assert!(state.writer);

                released = true;
                state.writer = false;
            }

            Directive::NotifyAll
        });
    }

    fn downgrade(sync: &Self::Sync) {
        let mut released = false;
        sync.monitor.enter(|state| {
            if !released {
                debug_assert!(state.readers == 0, "readers: {}", state.readers);
                debug_assert!(state.writer);

                released = true;
                state.writer = false;
                state.readers = 1;
            }

            Directive::NotifyAll
        });
    }

    fn try_upgrade(sync: &Self::Sync, duration: Duration) -> bool {
        let mut deadline = Deadline::lazy_after(duration);
        let mut acquired = false;
        let mut self_writer_pending = false;
        sync.monitor.enter(|state| {
            if !acquired {
                debug_assert!(!state.writer);

                if state.readers == 1 {
                    acquired = true;
                    state.readers = 0;
                    state.writer = true;
                } else if !state.writer_pending {
                    self_writer_pending = true;
                    state.writer_pending = true;
                }
            }

            if acquired {
                Directive::Return
            } else {
                Directive::Wait(deadline.remaining())
            }
        });

        if self_writer_pending {
            let mut cleared_writer_pending = false;
            sync.monitor.enter(|state| {
                if !cleared_writer_pending {
                    cleared_writer_pending = true;
                    state.writer_pending = false;
                }

                if acquired {
                    Directive::Return
                } else {
                    Directive::NotifyAll
                }
            });
        }

        acquired
    }
}

#[cfg(test)]
mod tests;