1#[macro_export]
2macro_rules! tokio_async_drop {
3 ($drop:block) => {
4 tokio::task::block_in_place(|| {
5 tokio::runtime::Handle::current().block_on(async { $drop });
6 });
7 };
8}
9
10#[cfg(test)]
11mod tests {
12 use super::*;
13
14 struct Foo<'a> {
15 inner: &'a mut u8,
16 }
17
18 impl<'a> Foo<'a> {
19 async fn bar(&mut self) {
20 *self.inner = 1;
21 }
22 }
23
24 impl<'a> Drop for Foo<'a> {
25 fn drop(&mut self) {
26 tokio_async_drop!({
27 self.bar().await;
28 });
29 }
30 }
31
32 fn test_core() {
33 let mut semaphore = 0;
34 let f = Foo {
35 inner: &mut semaphore,
36 };
37 drop(f);
38 assert_eq!(semaphore, 1);
39 }
40
41 #[test]
42 #[should_panic(
43 expected = "there is no reactor running, must be called from the context of a Tokio 1.x runtime"
44 )]
45 fn no_runtime() {
46 test_core();
47 }
48
49 #[test]
50 #[should_panic(expected = "can call blocking only when running on the multi-threaded runtime")]
51 fn current_thread() {
52 tokio::runtime::Builder::new_current_thread()
53 .enable_all()
54 .build()
55 .unwrap()
56 .block_on(async {
57 test_core();
58 });
59 }
60
61 #[test]
62 fn multi_thread() {
63 tokio::runtime::Builder::new_multi_thread()
64 .enable_all()
65 .build()
66 .unwrap()
67 .block_on(async {
68 test_core();
69 });
70 }
71}