use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
const RAW_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
|_| RAW_WAKER_INSTANCE, |_| {}, |_| {}, |_| {}, );
const RAW_WAKER_INSTANCE: RawWaker = RawWaker::new(core::ptr::null(), &RAW_WAKER_VTABLE);
#[inline]
fn noop_waker() -> Waker {
unsafe { Waker::from_raw(RAW_WAKER_INSTANCE) }
}
#[inline]
pub fn block_on<F: Future>(mut future: F) -> F::Output {
let waker = noop_waker();
let mut cx = Context::from_waker(&waker);
loop {
let pinned = unsafe { Pin::new_unchecked(&mut future) };
match pinned.poll(&mut cx) {
Poll::Ready(result) => return result,
Poll::Pending => {
#[cfg(feature = "std")]
std::thread::yield_now();
#[cfg(not(feature = "std"))]
core::hint::spin_loop();
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_block_on_ready() {
let result = block_on(async { 42 });
assert_eq!(result, 42);
}
#[test]
fn test_block_on_with_yield() {
use crate::async_vm::YieldNow;
let result = block_on(async {
let mut sum = 0;
for i in 0..5 {
sum += i;
YieldNow::new().await;
}
sum
});
assert_eq!(result, 10);
}
}