| 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 | |