Skip to content

Commit bdab64b

Browse files
committed
add ParkThread implementation of Park
1 parent ce71baf commit bdab64b

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

futures-executor/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@ pub use crate::enter::{enter, Enter, EnterError};
3535
mod park;
3636
#[cfg(feature = "std")]
3737
pub use crate::park::{Park, ParkDuration};
38+
39+
#[cfg(feature = "std")]
40+
mod park_thread;
41+
#[cfg(feature = "std")]
42+
pub use crate::park_thread::{ParkThread};

futures-executor/src/park_thread.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use crate::enter::Enter;
2+
use crate::park::{Park, ParkDuration};
3+
use std::sync::Arc;
4+
use std::thread;
5+
use futures_util::task::{waker_ref, ArcWake, WakerRef};
6+
7+
/// Implements [`Park`][p] using [`thread::park`] to put the thread to
8+
/// sleep.
9+
///
10+
/// [`thread::park`]: https://doc.rust-lang.org/std/thread/fn.park.html
11+
/// [p]: ../park/trait.Park.html
12+
#[derive(Debug)]
13+
pub struct ParkThread {
14+
// store a copy of TLS data here to `waker()` below can return a
15+
// reference to it
16+
notify: Arc<ThreadNotify>
17+
}
18+
19+
impl ParkThread {
20+
/// Create new `ParkThread` instance.
21+
pub fn new() -> Self {
22+
ParkThread {
23+
notify: CURRENT_THREAD_NOTIFY.with(Arc::clone),
24+
}
25+
}
26+
}
27+
28+
impl Default for ParkThread {
29+
fn default() -> Self {
30+
ParkThread::new()
31+
}
32+
}
33+
34+
impl Park for ParkThread {
35+
type Error = std::convert::Infallible;
36+
37+
fn waker(&self) -> WakerRef<'_> {
38+
waker_ref(&self.notify)
39+
}
40+
41+
fn park(&mut self, _enter: &mut Enter, duration: ParkDuration) -> Result<(), Self::Error> {
42+
match duration {
43+
ParkDuration::Poll => (),
44+
ParkDuration::Block => thread::park(),
45+
ParkDuration::Timeout(duration) => thread::park_timeout(duration),
46+
}
47+
Ok(())
48+
}
49+
}
50+
51+
thread_local! {
52+
// allocate only once per thread
53+
static CURRENT_THREAD_NOTIFY: Arc<ThreadNotify> = Arc::new(ThreadNotify {
54+
thread: thread::current(),
55+
});
56+
}
57+
58+
#[derive(Debug)]
59+
struct ThreadNotify {
60+
thread: thread::Thread,
61+
}
62+
63+
impl ArcWake for ThreadNotify {
64+
fn wake_by_ref(arc_self: &Arc<Self>) {
65+
arc_self.thread.unpark();
66+
}
67+
}

0 commit comments

Comments
 (0)