]> git.proxmox.com Git - rustc.git/blob - src/libstd/sync/mpsc/blocking.rs
Imported Upstream version 1.0.0~beta
[rustc.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::{self, 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 usize value. Useful for storing in a pipe's state
65 /// flag.
66 #[inline]
67 pub unsafe fn cast_to_usize(self) -> usize {
68 mem::transmute(self.inner)
69 }
70
71 /// Convert from an unsafe usize value. Useful for retrieving a pipe's state
72 /// flag.
73 #[inline]
74 pub unsafe fn cast_from_usize(signal_ptr: usize) -> 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 }