1use std::{
2 future::Future,
3 mem,
4 pin::{Pin, pin},
5 sync::{Arc, Condvar, Mutex},
6 task::{Context, Poll, Wake, Waker},
7};
8
9pub fn yield_now() -> impl Future<Output = ()> {
10 struct YieldNow {
11 yielded: bool,
12 }
13 impl Future for YieldNow {
14 type Output = ();
15 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
16 if self.yielded {
17 return Poll::Ready(());
18 }
19 self.yielded = true;
20 cx.waker().wake_by_ref();
21 Poll::Pending
22 }
23 }
24 YieldNow { yielded: false }
25}
26
27pub fn block_on<Fut>(fut: Fut) -> Fut::Output
28where
29 Fut: Future,
30{
31 let mut fut = pin!(fut);
32
33 let signal = Arc::new(Signal::default());
34 let waker = Waker::from(signal.clone());
35 let mut cx = Context::from_waker(&waker);
36 loop {
37 match fut.as_mut().poll(&mut cx) {
38 Poll::Ready(val) => return val,
39 Poll::Pending => signal.wait_for_wakeup(),
40 }
41 }
42}
43
44const RUNNING: u8 = 0;
45const NOTIFIED: u8 = 1;
46const SLEEP: u8 = 2;
47
48#[derive(Default)]
49struct Signal {
50 state: Mutex<u8>,
51 signal: Condvar,
52}
53
54impl Signal {
55 fn wait_for_wakeup(&self) {
61 let mut state = self.state.lock().unwrap();
62 if *state == NOTIFIED {
63 *state = RUNNING;
64 } else {
65 *state = SLEEP;
66 'spurious_wakeups: loop {
67 state = self.signal.wait(state).unwrap();
68 if *state == NOTIFIED {
69 *state = RUNNING;
70 break 'spurious_wakeups;
71 }
72 }
73 }
74 }
75}
76
77impl Wake for Signal {
78 fn wake_by_ref(self: &Arc<Self>) {
79 let state = {
80 let mut state = self.state.lock().unwrap();
81 mem::replace(&mut *state, NOTIFIED)
82 };
83 if state == SLEEP {
84 self.signal.notify_one();
85 }
86 }
87
88 fn wake(self: Arc<Self>) {
89 self.wake_by_ref();
90 }
91}