blob: 990bcb7fc9bc1b00de4535930651d54c1eda5f09 (
plain)
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
|
// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.
//! A simple spin lock based thread parker. Used on platforms without better
//! parking facilities available.
use core::sync::atomic::{AtomicBool, Ordering};
use core::hint::spin_loop;
use std::thread;
use std::time::Instant;
// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
parked: AtomicBool,
}
impl super::ThreadParkerT for ThreadParker {
type UnparkHandle = UnparkHandle;
const IS_CHEAP_TO_CONSTRUCT: bool = true;
#[inline]
fn new() -> ThreadParker {
ThreadParker {
parked: AtomicBool::new(false),
}
}
#[inline]
unsafe fn prepare_park(&self) {
self.parked.store(true, Ordering::Relaxed);
}
#[inline]
unsafe fn timed_out(&self) -> bool {
self.parked.load(Ordering::Relaxed) != false
}
#[inline]
unsafe fn park(&self) {
while self.parked.load(Ordering::Acquire) != false {
spin_loop();
}
}
#[inline]
unsafe fn park_until(&self, timeout: Instant) -> bool {
while self.parked.load(Ordering::Acquire) != false {
if Instant::now() >= timeout {
return false;
}
spin_loop();
}
true
}
#[inline]
unsafe fn unpark_lock(&self) -> UnparkHandle {
// We don't need to lock anything, just clear the state
self.parked.store(false, Ordering::Release);
UnparkHandle(())
}
}
pub struct UnparkHandle(());
impl super::UnparkHandleT for UnparkHandle {
#[inline]
unsafe fn unpark(self) {}
}
#[inline]
pub fn thread_yield() {
thread::yield_now();
}
|