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