1 | use std::future::Future; |
2 | use std::pin::Pin; |
3 | |
4 | use crate::task::{Context, Poll, Task}; |
5 | |
6 | /// A handle that awaits the result of a task. |
7 | /// |
8 | /// Dropping a [`JoinHandle`] will detach the task, meaning that there is no longer |
9 | /// a handle to the task and no way to `join` on it. |
10 | /// |
11 | /// Created when a task is [spawned]. |
12 | /// |
13 | /// [spawned]: fn.spawn.html |
14 | #[derive (Debug)] |
15 | pub struct JoinHandle<T> { |
16 | handle: Option<InnerHandle<T>>, |
17 | task: Task, |
18 | } |
19 | |
20 | #[cfg (not(target_os = "unknown" ))] |
21 | type InnerHandle<T> = async_global_executor::Task<T>; |
22 | #[cfg (target_arch = "wasm32" )] |
23 | type InnerHandle<T> = futures_channel::oneshot::Receiver<T>; |
24 | |
25 | impl<T> JoinHandle<T> { |
26 | /// Creates a new `JoinHandle`. |
27 | pub(crate) fn new(inner: InnerHandle<T>, task: Task) -> JoinHandle<T> { |
28 | JoinHandle { |
29 | handle: Some(inner), |
30 | task, |
31 | } |
32 | } |
33 | |
34 | /// Returns a handle to the underlying task. |
35 | /// |
36 | /// # Examples |
37 | /// |
38 | /// ``` |
39 | /// # async_std::task::block_on(async { |
40 | /// # |
41 | /// use async_std::task; |
42 | /// |
43 | /// let handle = task::spawn(async { |
44 | /// 1 + 2 |
45 | /// }); |
46 | /// println!("id = {}" , handle.task().id()); |
47 | /// # |
48 | /// # }) |
49 | pub fn task(&self) -> &Task { |
50 | &self.task |
51 | } |
52 | |
53 | /// Cancel this task. |
54 | #[cfg (not(target_os = "unknown" ))] |
55 | pub async fn cancel(mut self) -> Option<T> { |
56 | let handle = self.handle.take().unwrap(); |
57 | handle.cancel().await |
58 | } |
59 | |
60 | /// Cancel this task. |
61 | #[cfg (target_arch = "wasm32" )] |
62 | pub async fn cancel(mut self) -> Option<T> { |
63 | let mut handle = self.handle.take().unwrap(); |
64 | handle.close(); |
65 | handle.await.ok() |
66 | } |
67 | } |
68 | |
69 | #[cfg (not(target_os = "unknown" ))] |
70 | impl<T> Drop for JoinHandle<T> { |
71 | fn drop(&mut self) { |
72 | if let Some(handle: Task) = self.handle.take() { |
73 | handle.detach(); |
74 | } |
75 | } |
76 | } |
77 | |
78 | impl<T> Future for JoinHandle<T> { |
79 | type Output = T; |
80 | |
81 | #[cfg (not(target_os = "unknown" ))] |
82 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
83 | Pin::new(&mut self.handle.as_mut().unwrap()).poll(cx) |
84 | } |
85 | |
86 | #[cfg (target_arch = "wasm32" )] |
87 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
88 | match Pin::new(&mut self.handle.as_mut().unwrap()).poll(cx) { |
89 | Poll::Ready(Ok(t)) => Poll::Ready(t), |
90 | Poll::Ready(Err(_)) => unreachable!("channel must not be canceled" ), |
91 | Poll::Pending => Poll::Pending, |
92 | } |
93 | } |
94 | } |
95 | |