use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Mutex, Condvar};
use std::usize;
use sleep::Sleep;
pub trait Latch: LatchProbe {
fn set(&self);
}
pub trait LatchProbe {
fn probe(&self) -> bool;
}
pub struct SpinLatch {
b: AtomicBool,
}
impl SpinLatch {
#[inline]
pub fn new() -> SpinLatch {
SpinLatch { b: AtomicBool::new(false) }
}
}
impl LatchProbe for SpinLatch {
#[inline]
fn probe(&self) -> bool {
self.b.load(Ordering::SeqCst)
}
}
impl Latch for SpinLatch {
#[inline]
fn set(&self) {
self.b.store(true, Ordering::SeqCst);
}
}
pub struct LockLatch {
m: Mutex<bool>,
v: Condvar,
}
impl LockLatch {
#[inline]
pub fn new() -> LockLatch {
LockLatch {
m: Mutex::new(false),
v: Condvar::new(),
}
}
pub fn wait(&self) {
let mut guard = self.m.lock().unwrap();
while !*guard {
guard = self.v.wait(guard).unwrap();
}
}
}
impl LatchProbe for LockLatch {
#[inline]
fn probe(&self) -> bool {
let guard = self.m.lock().unwrap();
*guard
}
}
impl Latch for LockLatch {
#[inline]
fn set(&self) {
let mut guard = self.m.lock().unwrap();
*guard = true;
self.v.notify_all();
}
}
#[derive(Debug)]
pub struct CountLatch {
counter: AtomicUsize,
}
impl CountLatch {
#[inline]
pub fn new() -> CountLatch {
CountLatch { counter: AtomicUsize::new(1) }
}
#[inline]
pub fn increment(&self) {
debug_assert!(!self.probe());
self.counter.fetch_add(1, Ordering::Relaxed);
}
}
impl LatchProbe for CountLatch {
#[inline]
fn probe(&self) -> bool {
self.counter.load(Ordering::SeqCst) == 0
}
}
impl Latch for CountLatch {
#[inline]
fn set(&self) {
self.counter.fetch_sub(1, Ordering::SeqCst);
}
}
pub struct TickleLatch<'a, L: Latch> {
inner: L,
sleep: &'a Sleep,
}
impl<'a, L: Latch> TickleLatch<'a, L> {
#[inline]
pub fn new(latch: L, sleep: &'a Sleep) -> Self {
TickleLatch {
inner: latch,
sleep: sleep,
}
}
}
impl<'a, L: Latch> LatchProbe for TickleLatch<'a, L> {
#[inline]
fn probe(&self) -> bool {
self.inner.probe()
}
}
impl<'a, L: Latch> Latch for TickleLatch<'a, L> {
#[inline]
fn set(&self) {
self.inner.set();
self.sleep.tickle(usize::MAX);
}
}