     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96

    // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
    // file at the top-level directory of this distribution and at
    // http://rust-lang.org/COPYRIGHT.
    //
    // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
    // option. This file may not be copied, modified, or distributed
    // except according to those terms.

    //! Generic support for building blocking abstractions.

    use thread::{self, Thread};
    use sync::atomic::{AtomicBool, Ordering};
    use sync::Arc;
    use mem;
    use time::Instant;

    struct Inner {
        thread: Thread,
        woken: AtomicBool,
    }

    unsafe impl Send for Inner {}
    unsafe impl Sync for Inner {}

    #[derive(Clone)]
    pub struct SignalToken {
        inner: Arc<Inner>,
    }

    pub struct WaitToken {
        inner: Arc<Inner>,
    }

    impl !Send for WaitToken {}

    impl !Sync for WaitToken {}

    pub fn tokens() -> (WaitToken, SignalToken) {
        let inner = Arc::new(Inner {
            thread: thread::current(),
            woken: AtomicBool::new(false),
        });
        let wait_token = WaitToken {
            inner: inner.clone(),
        };
        let signal_token = SignalToken {
            inner: inner
        };
        (wait_token, signal_token)
    }

    impl SignalToken {
        pub fn signal(&self) -> bool {
            let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
            if wake {
                self.inner.thread.unpark();
            }
            wake
        }

        /// Convert to an unsafe usize value. Useful for storing in a pipe's state
        /// flag.
        #[inline]
        pub unsafe fn cast_to_usize(self) -> usize {
            mem::transmute(self.inner)
        }

        /// Convert from an unsafe usize value. Useful for retrieving a pipe's state
        /// flag.
        #[inline]
        pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken {
            SignalToken { inner: mem::transmute(signal_ptr) }
        }
    }

    impl WaitToken {
        pub fn wait(self) {
            while !self.inner.woken.load(Ordering::SeqCst) {
                thread::park()
            }
        }

        /// Returns true if we wake up normally, false otherwise.
        pub fn wait_max_until(self, end: Instant) -> bool {
            while !self.inner.woken.load(Ordering::SeqCst) {
                let now = Instant::now();
                if now >= end {
                    return false;
                }
                thread::park_timeout(end - now)
            }
            true
        }
    }

# Help

## Keyboard Shortcuts

?
  Show this help dialog
S
  Focus the search field
⇤
  Move up in search results
⇥
  Move down in search results
⏎
  Go to active search result
+
  Collapse/expand all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)