tokio_async_drop/
lib.rs

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}