use std::{fmt, panic::Location, pin::Pin, task::Context, task::Poll, task::ready};
use crate::remote::RemoteJoin;
type Task<T> = crate::rt::task::Task<T>;
pub(crate) type SpawnLocation = &'static Location<'static>;
#[derive(Debug)]
pub struct JoinHandle<T> {
task: Task<T>,
}
impl<T> JoinHandle<T> {
pub(crate) fn new(task: Task<T>) -> Self {
JoinHandle { task }
}
#[must_use]
pub fn cancel_on_drop(self) -> Self {
self.task.set_cancel_on_drop(true);
self
}
pub fn cancel(self) {
self.task.cancel();
}
#[deprecated(
since = "4.5.0",
note = "Drop the handle instead if cancel_on_drop() is not enabled"
)]
pub fn detach(self) {
self.task.set_cancel_on_drop(false);
}
pub fn is_finished(&self) -> bool {
self.task.is_finished()
}
}
impl<T> Future for JoinHandle<T> {
type Output = Result<T, JoinError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.task.poll_join(cx).map(|out| out.ok_or(JoinError))
}
}
#[derive(Debug)]
pub struct RemoteJoinHandle<T> {
inner: Inner<T>,
}
#[derive(Debug)]
enum Inner<T> {
Local(JoinHandle<T>),
Remote(RemoteJoin<T>),
}
impl<T> RemoteJoinHandle<T> {
pub(crate) fn local(task: JoinHandle<T>) -> Self {
Self {
inner: Inner::Local(task),
}
}
pub(crate) fn remote(join: RemoteJoin<T>) -> Self {
Self {
inner: Inner::Remote(join),
}
}
pub fn cancel(self) {
match self.inner {
Inner::Local(t) => t.cancel(),
Inner::Remote(t) => t.cancel(),
}
}
#[deprecated(since = "4.5.0", note = "Use drop(handle) instead")]
pub fn detach(self) {}
pub fn is_finished(&self) -> bool {
match &self.inner {
Inner::Local(t) => t.is_finished(),
Inner::Remote(t) => t.is_finished(),
}
}
}
impl<T> Future for RemoteJoinHandle<T> {
type Output = Result<T, JoinError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready(match &mut self.inner {
Inner::Local(t) => ready!(Pin::new(t).poll(cx)),
Inner::Remote(t) => ready!(t.poll_join(cx)).ok_or(JoinError),
})
}
}
#[derive(Debug, Copy, Clone)]
pub struct JoinError;
impl fmt::Display for JoinError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "JoinError")
}
}
impl std::error::Error for JoinError {}
#[cfg(test)]
#[path = "../tests/unit/handle.rs"]
mod tests;