use futures::channel::oneshot;
use std::future::Future;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
pub type BoxedFuture = Pin<Box<dyn Future<Output = ()> + 'static>>;
pub trait Executor {
fn execute(&self, fut: BoxedFuture) -> BoxedFuture;
}
impl<'a> Default for &'a dyn Executor {
fn default() -> &'a dyn Executor {
{
struct DefaultExecutor;
impl Executor for DefaultExecutor {
fn execute(&self, future: BoxedFuture) -> BoxedFuture {
#[cfg(target_arch = "wasm32")]
return future;
#[cfg(not(target_arch = "wasm32"))]
{
use futures::FutureExt;
deno_unsync::spawn(future).map(|v| v.unwrap()).boxed_local()
}
}
}
&DefaultExecutor
}
}
}
pub(crate) struct JoinHandle<T> {
rx: oneshot::Receiver<T>,
fut: BoxedFuture,
}
impl<T> Future for JoinHandle<T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
if let Poll::Ready(()) = Pin::new(&mut self.fut).poll(cx) {
match Pin::new(&mut self.rx).poll(cx) {
Poll::Ready(Ok(res)) => Poll::Ready(res),
_ => {
panic!("task panic");
}
}
} else {
Poll::Pending
}
}
}
pub(crate) fn spawn<F, T: 'static>(
executor: &dyn Executor,
f: F,
) -> JoinHandle<T>
where
F: Future<Output = T> + 'static,
{
let (tx, rx) = oneshot::channel();
let fut = executor.execute(Box::pin(async move {
tx.send(f.await).ok();
}));
JoinHandle { rx, fut }
}