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 | /// See also [the module level docs] for more information on cancellation. |
35 | /// |
36 | /// [cancelled]: method@super::error::JoinError::is_cancelled |
37 | /// [`JoinHandle::abort`]: method@super::JoinHandle::abort |
38 | /// [the module level docs]: crate::task#cancellation |
39 | pub fn abort(&self) { |
40 | self.raw.remote_abort(); |
41 | } |
42 | |
43 | /// Checks if the task associated with this `AbortHandle` has finished. |
44 | /// |
45 | /// Please note that this method can return `false` even if `abort` has been |
46 | /// called on the task. This is because the cancellation process may take |
47 | /// some time, and this method does not return `true` until it has |
48 | /// completed. |
49 | pub fn is_finished(&self) -> bool { |
50 | let state = self.raw.state().load(); |
51 | state.is_complete() |
52 | } |
53 | |
54 | /// Returns a [task ID] that uniquely identifies this task relative to other |
55 | /// currently spawned tasks. |
56 | /// |
57 | /// **Note**: This is an [unstable API][unstable]. The public API of this type |
58 | /// may break in 1.x releases. See [the documentation on unstable |
59 | /// features][unstable] for details. |
60 | /// |
61 | /// [task ID]: crate::task::Id |
62 | /// [unstable]: crate#unstable-features |
63 | #[cfg (tokio_unstable)] |
64 | #[cfg_attr (docsrs, doc(cfg(tokio_unstable)))] |
65 | pub fn id(&self) -> super::Id { |
66 | // Safety: The header pointer is valid. |
67 | unsafe { Header::get_id(self.raw.header_ptr()) } |
68 | } |
69 | } |
70 | |
71 | unsafe impl Send for AbortHandle {} |
72 | unsafe impl Sync for AbortHandle {} |
73 | |
74 | impl UnwindSafe for AbortHandle {} |
75 | impl RefUnwindSafe for AbortHandle {} |
76 | |
77 | impl fmt::Debug for AbortHandle { |
78 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
79 | // Safety: The header pointer is valid. |
80 | let id_ptr: NonNull = unsafe { Header::get_id_ptr(self.raw.header_ptr()) }; |
81 | let id: &Id = unsafe { id_ptr.as_ref() }; |
82 | fmt.debug_struct("AbortHandle" ).field(name:"id" , value:id).finish() |
83 | } |
84 | } |
85 | |
86 | impl Drop for AbortHandle { |
87 | fn drop(&mut self) { |
88 | self.raw.drop_abort_handle(); |
89 | } |
90 | } |
91 | |