tokio_util/task/
abort_on_drop.rs1use tokio::task::{AbortHandle, JoinError, JoinHandle};
5
6use std::{
7 future::Future,
8 mem::ManuallyDrop,
9 pin::Pin,
10 task::{Context, Poll},
11};
12
13#[must_use = "Dropping the handle aborts the task immediately"]
18pub struct AbortOnDropHandle<T>(JoinHandle<T>);
19
20impl<T> Drop for AbortOnDropHandle<T> {
21 fn drop(&mut self) {
22 self.0.abort()
23 }
24}
25
26impl<T> AbortOnDropHandle<T> {
27 pub fn new(handle: JoinHandle<T>) -> Self {
29 Self(handle)
30 }
31
32 pub fn abort(&self) {
35 self.0.abort()
36 }
37
38 pub fn is_finished(&self) -> bool {
41 self.0.is_finished()
42 }
43
44 pub fn abort_handle(&self) -> AbortHandle {
47 self.0.abort_handle()
48 }
49
50 pub fn detach(self) -> JoinHandle<T> {
52 let this = ManuallyDrop::new(self);
54 unsafe { std::ptr::read(&this.0) }
57 }
58}
59
60impl<T> std::fmt::Debug for AbortOnDropHandle<T> {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 f.debug_struct("AbortOnDropHandle")
63 .field("id", &self.0.id())
64 .finish()
65 }
66}
67
68impl<T> Future for AbortOnDropHandle<T> {
69 type Output = Result<T, JoinError>;
70
71 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
72 Pin::new(&mut self.0).poll(cx)
73 }
74}
75
76impl<T> AsRef<JoinHandle<T>> for AbortOnDropHandle<T> {
77 fn as_ref(&self) -> &JoinHandle<T> {
78 &self.0
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 struct NotDebug;
88
89 fn is_debug<T: std::fmt::Debug>() {}
90
91 #[test]
92 fn assert_debug() {
93 is_debug::<AbortOnDropHandle<NotDebug>>();
94 }
95}