fumio_utils/park/
park_thread.rs

1use futures_executor::Enter;
2use futures_util::task::{ArcWake, waker};
3use std::sync::Arc;
4use std::task::Waker;
5use std::thread::{self, Thread};
6use std::time::Duration;
7
8/// `ParkThread` implements `Park` by suspending the local thread until interrupted.
9///
10/// Only available with the `park-thread` feature for `fumio-utils` (enabled by default).
11#[derive(Debug)]
12pub struct ParkThread(());
13
14impl ParkThread {
15	/// Create new `ParkThread` instance.
16	#[allow(clippy::missing_const_for_fn)] // perhaps one day the impl needs non-const
17	pub fn new() -> Self {
18		Self(())
19	}
20}
21
22impl Default for ParkThread {
23	fn default() -> Self {
24		Self::new()
25	}
26}
27
28impl crate::park::Park for ParkThread {
29	fn waker(&self) -> Waker {
30		waker(CURRENT_THREAD_NOTIFY.with(Arc::clone))
31	}
32
33	fn park(&mut self, _enter: &mut Enter, duration: Option<Duration>) {
34		if let Some(duration) = duration {
35			if duration == Duration::new(0, 0) {
36				return; // don't park at all
37			}
38			thread::park_timeout(duration);
39		} else {
40			thread::park();
41		}
42	}
43}
44
45struct ThreadNotify {
46	thread: Thread,
47}
48
49thread_local! {
50	// allocate only once per thread
51	static CURRENT_THREAD_NOTIFY: Arc<ThreadNotify> = Arc::new(ThreadNotify {
52		thread: thread::current(),
53	});
54}
55
56impl ArcWake for ThreadNotify {
57	fn wake_by_ref(arc_self: &Arc<Self>) {
58		arc_self.thread.unpark();
59	}
60}