diff options
author | Joel Galenson <jgalenson@google.com> | 2020-10-23 09:39:31 -0700 |
---|---|---|
committer | Joel Galenson <jgalenson@google.com> | 2020-10-23 09:52:09 -0700 |
commit | d5495b03381a3ebe0805db353d198b285b535b5c (patch) | |
tree | 778b8524d15fca8b73db0253ee0e1919d0848bb6 /src/runtime/task/join.rs | |
parent | ba45c5bedf31df8562364c61d3dfb5262f10642e (diff) | |
download | tokio-d5495b03381a3ebe0805db353d198b285b535b5c.tar.gz |
Update to tokio-0.3.1 and add new features
Test: Build
Change-Id: I5b5b9b386a21982a019653d0cf0bd3afc505cfac
Diffstat (limited to 'src/runtime/task/join.rs')
-rw-r--r-- | src/runtime/task/join.rs | 110 |
1 files changed, 107 insertions, 3 deletions
diff --git a/src/runtime/task/join.rs b/src/runtime/task/join.rs index 3c4aabb..dedfb38 100644 --- a/src/runtime/task/join.rs +++ b/src/runtime/task/join.rs @@ -6,7 +6,7 @@ use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; -doc_rt_core! { +cfg_rt! { /// An owned permission to join on a task (await its termination). /// /// This can be thought of as the equivalent of [`std::thread::JoinHandle`] for @@ -45,6 +45,71 @@ doc_rt_core! { /// # } /// ``` /// + /// The generic parameter `T` in `JoinHandle<T>` is the return type of the spawned task. + /// If the return value is an i32, the join handle has type `JoinHandle<i32>`: + /// + /// ``` + /// use tokio::task; + /// + /// # async fn doc() { + /// let join_handle: task::JoinHandle<i32> = task::spawn(async { + /// 5 + 3 + /// }); + /// # } + /// + /// ``` + /// + /// If the task does not have a return value, the join handle has type `JoinHandle<()>`: + /// + /// ``` + /// use tokio::task; + /// + /// # async fn doc() { + /// let join_handle: task::JoinHandle<()> = task::spawn(async { + /// println!("I return nothing."); + /// }); + /// # } + /// ``` + /// + /// Note that `handle.await` doesn't give you the return type directly. It is wrapped in a + /// `Result` because panics in the spawned task are caught by Tokio. The `?` operator has + /// to be double chained to extract the returned value: + /// + /// ``` + /// use tokio::task; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> io::Result<()> { + /// let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async { + /// Ok(5 + 3) + /// }); + /// + /// let result = join_handle.await??; + /// assert_eq!(result, 8); + /// Ok(()) + /// } + /// ``` + /// + /// If the task panics, the error is a [`JoinError`] that contains the panic: + /// + /// ``` + /// use tokio::task; + /// use std::io; + /// use std::panic; + /// + /// #[tokio::main] + /// async fn main() -> io::Result<()> { + /// let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async { + /// panic!("boom"); + /// }); + /// + /// let err = join_handle.await.unwrap_err(); + /// assert!(err.is_panic()); + /// Ok(()) + /// } + /// + /// ``` /// Child being detached and outliving its parent: /// /// ```no_run @@ -56,7 +121,7 @@ doc_rt_core! { /// let original_task = task::spawn(async { /// let _detached_task = task::spawn(async { /// // Here we sleep to make sure that the first task returns before. - /// time::delay_for(Duration::from_millis(10)).await; + /// time::sleep(Duration::from_millis(10)).await; /// // This will be called, even though the JoinHandle is dropped. /// println!("♫ Still alive ♫"); /// }); @@ -68,13 +133,14 @@ doc_rt_core! { /// // We make sure that the new task has time to run, before the main /// // task returns. /// - /// time::delay_for(Duration::from_millis(1000)).await; + /// time::sleep(Duration::from_millis(1000)).await; /// # } /// ``` /// /// [`task::spawn`]: crate::task::spawn() /// [`task::spawn_blocking`]: crate::task::spawn_blocking /// [`std::thread::JoinHandle`]: std::thread::JoinHandle + /// [`JoinError`]: crate::task::JoinError pub struct JoinHandle<T> { raw: Option<RawTask>, _p: PhantomData<T>, @@ -91,6 +157,44 @@ impl<T> JoinHandle<T> { _p: PhantomData, } } + + /// Abort the task associated with the handle. + /// + /// Awaiting a cancelled task might complete as usual if the task was + /// already completed at the time it was cancelled, but most likely it + /// will complete with a `Err(JoinError::Cancelled)`. + /// + /// ```rust + /// use tokio::time; + /// + /// #[tokio::main] + /// async fn main() { + /// let mut handles = Vec::new(); + /// + /// handles.push(tokio::spawn(async { + /// time::sleep(time::Duration::from_secs(10)).await; + /// true + /// })); + /// + /// handles.push(tokio::spawn(async { + /// time::sleep(time::Duration::from_secs(10)).await; + /// false + /// })); + /// + /// for handle in &handles { + /// handle.abort(); + /// } + /// + /// for handle in handles { + /// assert!(handle.await.unwrap_err().is_cancelled()); + /// } + /// } + /// ``` + pub fn abort(&self) { + if let Some(raw) = self.raw { + raw.shutdown(); + } + } } impl<T> Unpin for JoinHandle<T> {} |