]> git.proxmox.com Git - rustc.git/blame - src/libstd/sync/mpsc/blocking.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / libstd / sync / mpsc / blocking.rs
CommitLineData
1a4d82fc
JJ
1//! Generic support for building blocking abstractions.
2
60c5eb7d 3use crate::mem;
532ac7d7
XL
4use crate::sync::atomic::{AtomicBool, Ordering};
5use crate::sync::Arc;
60c5eb7d 6use crate::thread::{self, Thread};
532ac7d7 7use crate::time::Instant;
1a4d82fc
JJ
8
9struct Inner {
10 thread: Thread,
11 woken: AtomicBool,
12}
13
14unsafe impl Send for Inner {}
15unsafe impl Sync for Inner {}
16
17#[derive(Clone)]
18pub struct SignalToken {
19 inner: Arc<Inner>,
20}
21
22pub struct WaitToken {
23 inner: Arc<Inner>,
1a4d82fc
JJ
24}
25
85aaf69f
SL
26impl !Send for WaitToken {}
27
28impl !Sync for WaitToken {}
29
1a4d82fc 30pub fn tokens() -> (WaitToken, SignalToken) {
60c5eb7d
XL
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 };
1a4d82fc
JJ
34 (wait_token, signal_token)
35}
36
37impl SignalToken {
38 pub fn signal(&self) -> bool {
39 let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
40 if wake {
41 self.inner.thread.unpark();
42 }
43 wake
44 }
45
9fa01778 46 /// Converts to an unsafe usize value. Useful for storing in a pipe's state
1a4d82fc
JJ
47 /// flag.
48 #[inline]
c34b1796 49 pub unsafe fn cast_to_usize(self) -> usize {
1a4d82fc
JJ
50 mem::transmute(self.inner)
51 }
52
9fa01778 53 /// Converts from an unsafe usize value. Useful for retrieving a pipe's state
1a4d82fc
JJ
54 /// flag.
55 #[inline]
c34b1796 56 pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken {
1a4d82fc
JJ
57 SignalToken { inner: mem::transmute(signal_ptr) }
58 }
1a4d82fc
JJ
59}
60
61impl WaitToken {
62 pub fn wait(self) {
63 while !self.inner.woken.load(Ordering::SeqCst) {
85aaf69f 64 thread::park()
1a4d82fc
JJ
65 }
66 }
3157f602 67
9fa01778 68 /// Returns `true` if we wake up normally.
3157f602
XL
69 pub fn wait_max_until(self, end: Instant) -> bool {
70 while !self.inner.woken.load(Ordering::SeqCst) {
71 let now = Instant::now();
72 if now >= end {
73 return false;
74 }
75 thread::park_timeout(end - now)
76 }
77 true
78 }
1a4d82fc 79}