use super::{REACTOR, Reactor};
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, Waker};
pub fn block_on<F>(fut: F) -> F::Output
where
F: Future,
{
let reactor = Reactor::new();
let prev = REACTOR.replace(Some(reactor.clone()));
if prev.is_some() {
panic!("cannot wstd::runtime::block_on inside an existing block_on!")
}
#[allow(unsafe_code)]
let root_task = unsafe { reactor.spawn_unchecked(fut) };
loop {
match reactor.pop_ready_list() {
None if reactor.pending_pollables_is_empty() => break,
None => reactor.block_on_pollables(),
Some(runnable) => {
let last_run_awake = runnable.run();
if last_run_awake || !reactor.ready_list_is_empty() {
reactor.nonblock_check_pollables();
}
}
}
}
REACTOR.replace(None);
let mut root_task = pin!(root_task);
let mut noop_context = Context::from_waker(Waker::noop());
match root_task.as_mut().poll(&mut noop_context) {
Poll::Ready(res) => res,
Poll::Pending => {
unreachable!(
"ready list empty, therefore root task should be ready. malformed root task?"
)
}
}
}