1use std::future::Future;
2use std::thread::panicking;
3
4impl<Fut> OnUncompletedDrop for Fut where Fut: Future + Send {}
5
6pub trait OnUncompletedDrop: Future + Send + Sized {
7 fn on_uncompleted_drop<F>(self, panic: bool, f: F) -> impl Future<Output = Self::Output> + Send
11 where
12 F: FnOnce() + Send,
13 {
14 let drop_guard = UncompletedDropGuard { f: Some(f), panic };
15 async move {
16 let output = self.await;
17 core::mem::forget(drop_guard);
18 output
19 }
20 }
21}
22
23struct UncompletedDropGuard<F>
24where
25 F: FnOnce() + Send,
26{
27 f: Option<F>,
28 panic: bool,
29}
30
31impl<F> Drop for UncompletedDropGuard<F>
32where
33 F: FnOnce() + Send,
34{
35 fn drop(&mut self) {
36 if let Some(f) = self.f.take() {
37 if self.panic || !panicking() {
38 f()
39 }
40 }
41 }
42}
43
44impl<Fut> OnUncompletedDropLocal for Fut where Fut: Future {}
45
46pub trait OnUncompletedDropLocal: Future + Sized {
47 fn on_uncompleted_drop_local<F: FnOnce()>(
51 self,
52 panic: bool,
53 f: F,
54 ) -> impl Future<Output = Self::Output> {
55 let drop_guard = UncompletedDropGuardLocal { f: Some(f), panic };
56 async move {
57 let output = self.await;
58 core::mem::forget(drop_guard);
59 output
60 }
61 }
62}
63
64struct UncompletedDropGuardLocal<F>
65where
66 F: FnOnce(),
67{
68 f: Option<F>,
69 panic: bool,
70}
71
72impl<F> Drop for UncompletedDropGuardLocal<F>
73where
74 F: FnOnce(),
75{
76 fn drop(&mut self) {
77 if let Some(f) = self.f.take() {
78 if self.panic || !panicking() {
79 f()
80 }
81 }
82 }
83}