]> git.lizzy.rs Git - rust.git/blob - src/libstd/sync/mpsc/blocking.rs
auto merge of #21008 : huonw/rust/trait-suggestions, r=nikomatsakis
[rust.git] / src / libstd / sync / mpsc / blocking.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Generic support for building blocking abstractions.
12
13 use thread::Thread;
14 use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
15 use sync::Arc;
16 use marker::{Sync, Send};
17 #[cfg(stage0)] // NOTE remove use after next snapshot
18 use marker::{NoSend, NoSync};
19 use mem;
20 use clone::Clone;
21
22 struct Inner {
23     thread: Thread,
24     woken: AtomicBool,
25 }
26
27 unsafe impl Send for Inner {}
28 unsafe impl Sync for Inner {}
29
30 #[derive(Clone)]
31 pub struct SignalToken {
32     inner: Arc<Inner>,
33 }
34
35 #[cfg(stage0)] // NOTE remove impl after next snapshot
36 pub struct WaitToken {
37     inner: Arc<Inner>,
38     no_send: NoSend,
39     no_sync: NoSync,
40 }
41
42 #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
43 pub struct WaitToken {
44     inner: Arc<Inner>,
45 }
46
47 #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
48 impl !Send for WaitToken {}
49
50 #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
51 impl !Sync for WaitToken {}
52
53 #[cfg(stage0)] // NOTE remove impl after next snapshot
54 pub fn tokens() -> (WaitToken, SignalToken) {
55     let inner = Arc::new(Inner {
56         thread: Thread::current(),
57         woken: ATOMIC_BOOL_INIT,
58     });
59     let wait_token = WaitToken {
60         inner: inner.clone(),
61         no_send: NoSend,
62         no_sync: NoSync,
63     };
64     let signal_token = SignalToken {
65         inner: inner
66     };
67     (wait_token, signal_token)
68 }
69
70 #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
71 pub fn tokens() -> (WaitToken, SignalToken) {
72     let inner = Arc::new(Inner {
73         thread: Thread::current(),
74         woken: ATOMIC_BOOL_INIT,
75     });
76     let wait_token = WaitToken {
77         inner: inner.clone(),
78     };
79     let signal_token = SignalToken {
80         inner: inner
81     };
82     (wait_token, signal_token)
83 }
84
85 impl SignalToken {
86     pub fn signal(&self) -> bool {
87         let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
88         if wake {
89             self.inner.thread.unpark();
90         }
91         wake
92     }
93
94     /// Convert to an unsafe uint value. Useful for storing in a pipe's state
95     /// flag.
96     #[inline]
97     pub unsafe fn cast_to_uint(self) -> uint {
98         mem::transmute(self.inner)
99     }
100
101     /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
102     /// flag.
103     #[inline]
104     pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
105         SignalToken { inner: mem::transmute(signal_ptr) }
106     }
107
108 }
109
110 impl WaitToken {
111     pub fn wait(self) {
112         while !self.inner.woken.load(Ordering::SeqCst) {
113             Thread::park()
114         }
115     }
116 }