use std::{
future::Future,
pin::Pin,
task::{
Context,
Poll,
},
};
use tokio::task::{
JoinError,
JoinHandle,
};
pub struct TokioExecution<R, E> {
handle: JoinHandle<Result<R, E>>,
}
impl<R, E> TokioExecution<R, E> {
#[inline]
pub(crate) fn new(handle: JoinHandle<Result<R, E>>) -> Self {
Self { handle }
}
#[inline]
pub fn is_finished(&self) -> bool {
self.handle.is_finished()
}
#[inline]
pub fn cancel(&self) -> bool {
self.handle.abort();
true
}
}
impl<R, E> Future for TokioExecution<R, E> {
type Output = Result<R, E>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
match Pin::new(&mut this.handle).poll(cx) {
Poll::Ready(Ok(result)) => Poll::Ready(result),
Poll::Ready(Err(error)) => handle_join_error(error),
Poll::Pending => Poll::Pending,
}
}
}
fn handle_join_error<R, E>(error: JoinError) -> Poll<Result<R, E>> {
if error.is_panic() {
std::panic::resume_unwind(error.into_panic());
}
panic!("tokio execution was cancelled before completion");
}