1use std::{fmt, panic::Location, pin::Pin, task::Context, task::Poll, task::ready};
2
3use crate::remote::RemoteJoin;
4
5type Task<T> = crate::rt::task::Task<T>;
6
7pub(crate) type SpawnLocation = &'static Location<'static>;
9
10#[derive(Debug)]
17pub struct JoinHandle<T> {
18 task: Task<T>,
19}
20
21impl<T> JoinHandle<T> {
22 pub(crate) fn new(task: Task<T>) -> Self {
23 JoinHandle { task }
24 }
25
26 pub fn cancel(self) {
31 self.task.cancel();
32 }
33
34 pub fn detach(self) {}
36
37 pub fn is_finished(&self) -> bool {
39 self.task.is_finished()
40 }
41}
42
43impl<T> Future for JoinHandle<T> {
44 type Output = Result<T, JoinError>;
45
46 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
47 self.task.poll_join(cx).map(|out| out.ok_or(JoinError))
48 }
49}
50
51#[derive(Debug)]
59pub struct RemoteJoinHandle<T> {
60 inner: Inner<T>,
61}
62
63#[derive(Debug)]
64enum Inner<T> {
65 Local(JoinHandle<T>),
66 Remote(RemoteJoin<T>),
67}
68
69impl<T> RemoteJoinHandle<T> {
70 pub(crate) fn local(task: JoinHandle<T>) -> Self {
71 Self {
72 inner: Inner::Local(task),
73 }
74 }
75
76 pub(crate) fn remote(join: RemoteJoin<T>) -> Self {
77 Self {
78 inner: Inner::Remote(join),
79 }
80 }
81
82 pub fn cancel(self) {
88 match self.inner {
89 Inner::Local(t) => t.cancel(),
90 Inner::Remote(t) => t.cancel(),
91 }
92 }
93
94 pub fn detach(self) {}
96
97 pub fn is_finished(&self) -> bool {
99 match &self.inner {
100 Inner::Local(t) => t.is_finished(),
101 Inner::Remote(t) => t.is_finished(),
102 }
103 }
104}
105
106impl<T> Future for RemoteJoinHandle<T> {
107 type Output = Result<T, JoinError>;
108
109 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
110 Poll::Ready(match &mut self.inner {
111 Inner::Local(t) => ready!(Pin::new(t).poll(cx)),
112 Inner::Remote(t) => ready!(t.poll_join(cx)).ok_or(JoinError),
113 })
114 }
115}
116
117#[derive(Debug, Copy, Clone)]
122pub struct JoinError;
123
124impl fmt::Display for JoinError {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "JoinError")
127 }
128}
129
130impl std::error::Error for JoinError {}
131
132#[cfg(all(test, not(feature = "tokio"), not(feature = "compio")))]
133#[path = "../tests/unit/handle.rs"]
134mod tests;