1 | use crate::runtime::task::{Header, RawTask}; |
2 | use std::fmt; |
3 | use std::panic::{RefUnwindSafe, UnwindSafe}; |
4 | |
5 | /// An owned permission to abort a spawned task, without awaiting its completion. |
6 | /// |
7 | /// Unlike a [`JoinHandle`], an `AbortHandle` does *not* represent the |
8 | /// permission to await the task's completion, only to terminate it. |
9 | /// |
10 | /// The task may be aborted by calling the [`AbortHandle::abort`] method. |
11 | /// Dropping an `AbortHandle` releases the permission to terminate the task |
12 | /// --- it does *not* abort the task. |
13 | /// |
14 | /// [`JoinHandle`]: crate::task::JoinHandle |
15 | #[cfg_attr (docsrs, doc(cfg(feature = "rt" )))] |
16 | pub struct AbortHandle { |
17 | raw: RawTask, |
18 | } |
19 | |
20 | impl AbortHandle { |
21 | pub(super) fn new(raw: RawTask) -> Self { |
22 | Self { raw } |
23 | } |
24 | |
25 | /// Abort the task associated with the handle. |
26 | /// |
27 | /// Awaiting a cancelled task might complete as usual if the task was |
28 | /// already completed at the time it was cancelled, but most likely it |
29 | /// will fail with a [cancelled] `JoinError`. |
30 | /// |
31 | /// If the task was already cancelled, such as by [`JoinHandle::abort`], |
32 | /// this method will do nothing. |
33 | /// |
34 | /// [cancelled]: method@super::error::JoinError::is_cancelled |
35 | /// [`JoinHandle::abort`]: method@super::JoinHandle::abort |
36 | pub fn abort(&self) { |
37 | self.raw.remote_abort(); |
38 | } |
39 | |
40 | /// Checks if the task associated with this `AbortHandle` has finished. |
41 | /// |
42 | /// Please note that this method can return `false` even if `abort` has been |
43 | /// called on the task. This is because the cancellation process may take |
44 | /// some time, and this method does not return `true` until it has |
45 | /// completed. |
46 | pub fn is_finished(&self) -> bool { |
47 | let state = self.raw.state().load(); |
48 | state.is_complete() |
49 | } |
50 | |
51 | /// Returns a [task ID] that uniquely identifies this task relative to other |
52 | /// currently spawned tasks. |
53 | /// |
54 | /// **Note**: This is an [unstable API][unstable]. The public API of this type |
55 | /// may break in 1.x releases. See [the documentation on unstable |
56 | /// features][unstable] for details. |
57 | /// |
58 | /// [task ID]: crate::task::Id |
59 | /// [unstable]: crate#unstable-features |
60 | #[cfg (tokio_unstable)] |
61 | #[cfg_attr (docsrs, doc(cfg(tokio_unstable)))] |
62 | pub fn id(&self) -> super::Id { |
63 | // Safety: The header pointer is valid. |
64 | unsafe { Header::get_id(self.raw.header_ptr()) } |
65 | } |
66 | } |
67 | |
68 | unsafe impl Send for AbortHandle {} |
69 | unsafe impl Sync for AbortHandle {} |
70 | |
71 | impl UnwindSafe for AbortHandle {} |
72 | impl RefUnwindSafe for AbortHandle {} |
73 | |
74 | impl fmt::Debug for AbortHandle { |
75 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
76 | // Safety: The header pointer is valid. |
77 | let id_ptr: NonNull = unsafe { Header::get_id_ptr(self.raw.header_ptr()) }; |
78 | let id: &Id = unsafe { id_ptr.as_ref() }; |
79 | fmt.debug_struct("AbortHandle" ).field(name:"id" , value:id).finish() |
80 | } |
81 | } |
82 | |
83 | impl Drop for AbortHandle { |
84 | fn drop(&mut self) { |
85 | self.raw.drop_abort_handle(); |
86 | } |
87 | } |
88 | |