From 83d0e7f8b3b207f8db57e75c7f7d2e384d26ec3b Mon Sep 17 00:00:00 2001 From: Name1e5s Date: Tue, 31 May 2022 17:22:09 +0800 Subject: [PATCH] runtime: add `is_finished` method for `JoinHandle` and `AbortHandle` (#4709) --- tokio/src/runtime/task/abort.rs | 16 ++++++++++++++ tokio/src/runtime/task/join.rs | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/tokio/src/runtime/task/abort.rs b/tokio/src/runtime/task/abort.rs index 4977377880d..3188394a8ea 100644 --- a/tokio/src/runtime/task/abort.rs +++ b/tokio/src/runtime/task/abort.rs @@ -49,6 +49,22 @@ impl AbortHandle { } } + /// Checks if the task associated with this `AbortHandle` has finished. + /// + /// Please note that this method can return `false` even if `abort` has been + /// called on the task. This is because the cancellation process may take + /// some time, and this method does not return `true` until it has + /// completed. + #[cfg_attr(not(tokio_unstable), allow(unreachable_pub))] + pub fn is_finished(&self) -> bool { + if let Some(raw) = self.raw { + let state = raw.header().state.load(); + state.is_complete() + } else { + true + } + } + /// Returns a [task ID] that uniquely identifies this task relative to other /// currently spawned tasks. /// diff --git a/tokio/src/runtime/task/join.rs b/tokio/src/runtime/task/join.rs index 86580c84b59..a04ec956a56 100644 --- a/tokio/src/runtime/task/join.rs +++ b/tokio/src/runtime/task/join.rs @@ -203,6 +203,43 @@ impl JoinHandle { } } + /// Checks if the task associated with this `JoinHandle` has finished. + /// + /// Please note that this method can return `false` even if [`abort`] has been + /// called on the task. This is because the cancellation process may take + /// some time, and this method does not return `true` until it has + /// completed. + /// + /// ```rust + /// use tokio::time; + /// + /// # #[tokio::main(flavor = "current_thread")] + /// # async fn main() { + /// # time::pause(); + /// let handle1 = tokio::spawn(async { + /// // do some stuff here + /// }); + /// let handle2 = tokio::spawn(async { + /// // do some other stuff here + /// time::sleep(time::Duration::from_secs(10)).await; + /// }); + /// // Wait for the task to finish + /// handle2.abort(); + /// time::sleep(time::Duration::from_secs(1)).await; + /// assert!(handle1.is_finished()); + /// assert!(handle2.is_finished()); + /// # } + /// ``` + /// [`abort`]: method@JoinHandle::abort + pub fn is_finished(&self) -> bool { + if let Some(raw) = self.raw { + let state = raw.header().state.load(); + state.is_complete() + } else { + true + } + } + /// Set the waker that is notified when the task completes. pub(crate) fn set_join_waker(&mut self, waker: &Waker) { if let Some(raw) = self.raw {