1 //! Generic support for building blocking abstractions.
4 use crate::sync::atomic::{AtomicBool, Ordering};
6 use crate::thread::{self, Thread};
7 use crate::time::Instant;
14 unsafe impl Send for Inner {}
15 unsafe impl Sync for Inner {}
18 pub struct SignalToken {
22 pub struct WaitToken {
26 impl !Send for WaitToken {}
28 impl !Sync for WaitToken {}
30 pub fn tokens() -> (WaitToken, SignalToken) {
31 let inner = Arc::new(Inner { thread: thread::current(), woken: AtomicBool::new(false) });
32 let wait_token = WaitToken { inner: inner.clone() };
33 let signal_token = SignalToken { inner };
34 (wait_token, signal_token)
38 pub fn signal(&self) -> bool {
42 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
45 self.inner.thread.unpark();
50 /// Converts to an unsafe usize value. Useful for storing in a pipe's state
53 pub unsafe fn cast_to_usize(self) -> usize {
54 mem::transmute(self.inner)
57 /// Converts from an unsafe usize value. Useful for retrieving a pipe's state
60 pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken {
61 SignalToken { inner: mem::transmute(signal_ptr) }
67 while !self.inner.woken.load(Ordering::SeqCst) {
72 /// Returns `true` if we wake up normally.
73 pub fn wait_max_until(self, end: Instant) -> bool {
74 while !self.inner.woken.load(Ordering::SeqCst) {
75 let now = Instant::now();
79 thread::park_timeout(end - now)