1 //! Generic support for building blocking abstractions.
3 use crate::sync::atomic::{AtomicBool, Ordering};
5 use crate::thread::{self, Thread};
6 use crate::time::Instant;
13 unsafe impl Send for Inner {}
14 unsafe impl Sync for Inner {}
17 pub struct SignalToken {
21 pub struct WaitToken {
25 impl !Send for WaitToken {}
27 impl !Sync for WaitToken {}
29 pub fn tokens() -> (WaitToken, SignalToken) {
30 let inner = Arc::new(Inner { thread: thread::current(), woken: AtomicBool::new(false) });
31 let wait_token = WaitToken { inner: inner.clone() };
32 let signal_token = SignalToken { inner };
33 (wait_token, signal_token)
37 pub fn signal(&self) -> bool {
41 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
44 self.inner.thread.unpark();
49 /// Converts to an unsafe raw pointer. Useful for storing in a pipe's state
52 pub unsafe fn to_raw(self) -> *mut u8 {
53 Arc::into_raw(self.inner) as *mut u8
56 /// Converts from an unsafe raw pointer. Useful for retrieving a pipe's state
59 pub unsafe fn from_raw(signal_ptr: *mut u8) -> SignalToken {
60 SignalToken { inner: Arc::from_raw(signal_ptr as *mut Inner) }
66 while !self.inner.woken.load(Ordering::SeqCst) {
71 /// Returns `true` if we wake up normally.
72 pub fn wait_max_until(self, end: Instant) -> bool {
73 while !self.inner.woken.load(Ordering::SeqCst) {
74 let now = Instant::now();
78 thread::park_timeout(end - now)