|
| 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