• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 Amanieu d'Antras
2 //
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
7 
8 //! A simple spin lock based thread parker. Used on platforms without better
9 //! parking facilities available.
10 
11 use core::hint::spin_loop;
12 use core::sync::atomic::{AtomicBool, Ordering};
13 use std::thread;
14 use std::time::Instant;
15 
16 // Helper type for putting a thread to sleep until some other thread wakes it up
17 pub struct ThreadParker {
18     parked: AtomicBool,
19 }
20 
21 impl super::ThreadParkerT for ThreadParker {
22     type UnparkHandle = UnparkHandle;
23 
24     const IS_CHEAP_TO_CONSTRUCT: bool = true;
25 
26     #[inline]
new() -> ThreadParker27     fn new() -> ThreadParker {
28         ThreadParker {
29             parked: AtomicBool::new(false),
30         }
31     }
32 
33     #[inline]
prepare_park(&self)34     unsafe fn prepare_park(&self) {
35         self.parked.store(true, Ordering::Relaxed);
36     }
37 
38     #[inline]
timed_out(&self) -> bool39     unsafe fn timed_out(&self) -> bool {
40         self.parked.load(Ordering::Relaxed) != false
41     }
42 
43     #[inline]
park(&self)44     unsafe fn park(&self) {
45         while self.parked.load(Ordering::Acquire) != false {
46             spin_loop();
47         }
48     }
49 
50     #[inline]
park_until(&self, timeout: Instant) -> bool51     unsafe fn park_until(&self, timeout: Instant) -> bool {
52         while self.parked.load(Ordering::Acquire) != false {
53             if Instant::now() >= timeout {
54                 return false;
55             }
56             spin_loop();
57         }
58         true
59     }
60 
61     #[inline]
unpark_lock(&self) -> UnparkHandle62     unsafe fn unpark_lock(&self) -> UnparkHandle {
63         // We don't need to lock anything, just clear the state
64         self.parked.store(false, Ordering::Release);
65         UnparkHandle(())
66     }
67 }
68 
69 pub struct UnparkHandle(());
70 
71 impl super::UnparkHandleT for UnparkHandle {
72     #[inline]
unpark(self)73     unsafe fn unpark(self) {}
74 }
75 
76 #[inline]
thread_yield()77 pub fn thread_yield() {
78     thread::yield_now();
79 }
80