unbounded-spsc 0.3.0

An unbounded spsc queue built from `bounded_spsc_queue`s
Documentation
use std;
use std::sync::{atomic, Arc};

pub(crate) struct Inner {
  thread : std::thread::Thread,
  woken  : atomic::AtomicBool
}
unsafe impl Send for Inner {}
unsafe impl Sync for Inner {}

pub(crate) struct WaitToken {
  inner : Arc <Inner>
}
impl !Send for WaitToken {}
impl !Sync for WaitToken {}

impl Inner {
  pub(crate) fn signal (&self) -> bool {
    let wake = self.woken.compare_exchange (
      false, true, atomic::Ordering::SeqCst, atomic::Ordering::SeqCst
    ).is_ok();
    if wake {
      self.thread.unpark();
    }
    wake
  }
}

impl WaitToken {
  pub(crate) fn wait (self) {
    while !self.inner.woken.load (atomic::Ordering::SeqCst) {
      std::thread::park()
    }
  }

  pub(crate) fn wait_max_until (self, end : std::time::Instant) -> bool {
    while !self.inner.woken.load (atomic::Ordering::SeqCst) {
      let now = std::time::Instant::now();
      if end <= now {
        return false;
      }
      std::thread::park_timeout (end - now)
    }
    true
  }
}

pub(crate) fn tokens() -> (WaitToken, Arc <Inner>) {
  let signal_token = Arc::new (Inner {
    thread: std::thread::current(),
    woken:  atomic::AtomicBool::new (false)
  });
  let wait_token = WaitToken {
    inner:  signal_token.clone()
  };
  (wait_token, signal_token)
}