1use std::sync::{Arc, Condvar, Mutex};
2use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
3
4#[derive(Default)]
5struct Park(Mutex<bool>, Condvar);
6
7fn unpark(park: &Park) {
8 *park.0.lock().unwrap() = true;
9 park.1.notify_one();
10}
11
12static VTABLE: RawWakerVTable = RawWakerVTable::new(
13 |clone_me| unsafe {
14 let arc = Arc::from_raw(clone_me as *const Park);
15 std::mem::forget(arc.clone());
16 RawWaker::new(Arc::into_raw(arc) as *const (), &VTABLE)
17 },
18 |wake_me| unsafe { unpark(&Arc::from_raw(wake_me as *const Park)) },
19 |wake_by_ref_me| unsafe { unpark(&*(wake_by_ref_me as *const Park)) },
20 |drop_me| unsafe { drop(Arc::from_raw(drop_me as *const Park)) },
21);
22
23pub fn run<F: std::future::Future>(mut f: F) -> F::Output {
25 let mut f = unsafe { std::pin::Pin::new_unchecked(&mut f) };
26 let park = Arc::new(Park::default());
27 let sender = Arc::into_raw(park.clone());
28 let raw_waker = RawWaker::new(sender as *const _, &VTABLE);
29 let waker = unsafe { Waker::from_raw(raw_waker) };
30 let mut cx = Context::from_waker(&waker);
31
32 loop {
33 match f.as_mut().poll(&mut cx) {
34 Poll::Pending => {
35 let mut runnable = park.0.lock().unwrap();
36 while !*runnable {
37 runnable = park.1.wait(runnable).unwrap();
38 }
39 *runnable = false;
40 }
41 Poll::Ready(val) => return val,
42 }
43 }
44}