1use crate::runtime::task::{Header, RawTask};
2use std::fmt;
3use 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")))]
16pub struct AbortHandle {
17 raw: RawTask,
18}
19
20impl 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
71unsafe impl Send for AbortHandle {}
72unsafe impl Sync for AbortHandle {}
73
74impl UnwindSafe for AbortHandle {}
75impl RefUnwindSafe for AbortHandle {}
76
77impl 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
86impl Drop for AbortHandle {
87 fn drop(&mut self) {
88 self.raw.drop_abort_handle();
89 }
90}
91