//! Most of the examples are just doing CPU-y operations, so just spinning is //! more efficient. use std::future::Future; use std::pin::pin; use std::ptr::null; use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; /// Spins, polling the provided future until it returns a result. This is /// preferable to something like `pollster` only if you know that your futures /// are CPU-bound and will never wait on anything. pub fn block_on(future: impl Future) -> T { let mut future = pin!(future); let waker = noop(); let mut context = Context::from_waker(&waker); loop { match future.as_mut().poll(&mut context) { Poll::Pending => continue, Poll::Ready(result) => break result, } } } /// Create a waker that does absolutely nothing. fn noop() -> Waker { const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop); const RAW: RawWaker = RawWaker::new(null(), &VTABLE); unsafe fn clone(_: *const ()) -> RawWaker { RAW } unsafe fn wake(_: *const ()) {} unsafe fn wake_by_ref(_: *const ()) {} unsafe fn drop(_: *const ()) {} // Safety: none of the functions do anything, and `clone` returns the // correct raw waker. unsafe { Waker::from_raw(RAW) } }