use std::sync::{Arc, Condvar, Mutex}; use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; #[cfg(feature = "bench")] mod bench; mod index; mod merge; mod new; mod search; mod serve; #[cfg(feature = "bench")] pub use self::bench::run_bench_cli; pub use self::index::run_index_cli; pub use self::merge::run_merge_cli; pub use self::new::run_new_cli; pub use self::search::run_search_cli; pub use self::serve::run_serve_cli; // stolen from [extreme](https://github.com/spacejam/extreme) #[derive(Default)] struct Park(Mutex, Condvar); fn unpark(park: &Park) { *park.0.lock().unwrap() = true; park.1.notify_one(); } static VTABLE: RawWakerVTable = RawWakerVTable::new( |clone_me| unsafe { let arc = Arc::from_raw(clone_me as *const Park); std::mem::forget(arc.clone()); RawWaker::new(Arc::into_raw(arc) as *const (), &VTABLE) }, |wake_me| unsafe { unpark(&Arc::from_raw(wake_me as *const Park)) }, |wake_by_ref_me| unsafe { unpark(&*(wake_by_ref_me as *const Park)) }, |drop_me| unsafe { drop(Arc::from_raw(drop_me as *const Park)) }, ); /// Run a `Future`. pub fn run(mut f: F) -> F::Output { let mut f = unsafe { std::pin::Pin::new_unchecked(&mut f) }; let park = Arc::new(Park::default()); let sender = Arc::into_raw(park.clone()); let raw_waker = RawWaker::new(sender as *const _, &VTABLE); let waker = unsafe { Waker::from_raw(raw_waker) }; let mut cx = Context::from_waker(&waker); loop { match f.as_mut().poll(&mut cx) { Poll::Pending => { let mut runnable = park.0.lock().unwrap(); while !*runnable { runnable = park.1.wait(runnable).unwrap(); } *runnable = false; } Poll::Ready(val) => return val, } } }