]> git.lizzy.rs Git - rust.git/blob - src/libstd/sync/mpsc/blocking.rs
Register snapshot for 9006c3c
[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 use mem;
18 use clone::Clone;
19
20 struct Inner {
21     thread: Thread,
22     woken: AtomicBool,
23 }
24
25 unsafe impl Send for Inner {}
26 unsafe impl Sync for Inner {}
27
28 #[derive(Clone)]
29 pub struct SignalToken {
30     inner: Arc<Inner>,
31 }
32
33 pub struct WaitToken {
34     inner: Arc<Inner>,
35 }
36
37 impl !Send for WaitToken {}
38
39 impl !Sync for WaitToken {}
40
41 pub fn tokens() -> (WaitToken, SignalToken) {
42     let inner = Arc::new(Inner {
43         thread: Thread::current(),
44         woken: ATOMIC_BOOL_INIT,
45     });
46     let wait_token = WaitToken {
47         inner: inner.clone(),
48     };
49     let signal_token = SignalToken {
50         inner: inner
51     };
52     (wait_token, signal_token)
53 }
54
55 impl SignalToken {
56     pub fn signal(&self) -> bool {
57         let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
58         if wake {
59             self.inner.thread.unpark();
60         }
61         wake
62     }
63
64     /// Convert to an unsafe uint value. Useful for storing in a pipe's state
65     /// flag.
66     #[inline]
67     pub unsafe fn cast_to_uint(self) -> uint {
68         mem::transmute(self.inner)
69     }
70
71     /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
72     /// flag.
73     #[inline]
74     pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
75         SignalToken { inner: mem::transmute(signal_ptr) }
76     }
77
78 }
79
80 impl WaitToken {
81     pub fn wait(self) {
82         while !self.inner.woken.load(Ordering::SeqCst) {
83             Thread::park()
84         }
85     }
86 }