use std::{
future::Future,
pin::Pin,
task::{
Context,
Poll,
},
};
use tokio::task::{
JoinError,
JoinHandle,
};
use qubit_executor::{
TaskExecutionError,
TaskResult,
};
pub struct TokioTaskHandle<R, E> {
handle: JoinHandle<TaskResult<R, E>>,
}
impl<R, E> TokioTaskHandle<R, E> {
#[inline]
pub(crate) fn new(handle: JoinHandle<TaskResult<R, E>>) -> Self {
Self { handle }
}
#[inline]
pub fn cancel(&self) -> bool {
self.handle.abort();
true
}
#[inline]
pub fn is_done(&self) -> bool {
self.handle.is_finished()
}
}
impl<R, E> Future for TokioTaskHandle<R, E> {
type Output = TaskResult<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)) => Poll::Ready(Err(join_error_to_task_error(error))),
Poll::Pending => Poll::Pending,
}
}
}
fn join_error_to_task_error<E>(error: JoinError) -> TaskExecutionError<E> {
if error.is_cancelled() {
TaskExecutionError::Cancelled
} else {
TaskExecutionError::Panicked
}
}