executioner/
lib.rs

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
23/// Run a `Future`.
24pub 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}