1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use Future;
/// Enables executing async operations within synchronous Drop implementations.
///
/// # Safety requirements
///
/// **WARNING**: This function requires a multithreaded tokio runtime to function correctly!
///
/// # How it works
///
/// 1. We are typically in a Drop implementation which is synchronous - it can't be async.
/// But we need to execute an async operation.
///
/// 2. `block_on` is needed because it takes an async operation and runs it to completion
/// synchronously - it's how we can execute async operations within synchronous contexts.
///
/// 3. However, `block_on` by itself isn't safe to call from within an async context
/// (which we are in since we're inside the Tokio runtime).
/// This is because it could lead to deadlocks - imagine if the current thread is needed to
/// process some task that our blocked async operation is waiting on.
///
/// 4. This is where `block_in_place` comes in - it tells Tokio:
/// "Hey, I'm about to block this thread, please make sure other threads are available to
/// still process tasks!". It essentially moves other tasks to another worker thread so that the
/// current thread becomes available to be blocked for an unknown amount of time.
///
/// 5. Note that `block_in_place` requires a multithreaded tokio runtime to be active!
/// So use `#[tokio::test(flavor = "multi_thread")]` in tokio-enabled tests.
///
/// 6. Also note that `block_in_place` enforces that the given closure is run to completion by
/// waiting indefinitely for it to finish when the async executor is terminated.
///
/// # Example
///
/// ```ignore
/// use crate::async_drop::run_future;
///
/// struct PerformsAsyncDrop {
/// // ... fields
/// }
///
/// impl Drop for PerformsAsyncDrop {
/// fn drop(&mut self) {
/// run_future(async {
/// // Perform async cleanup operations here
/// });
/// }
/// }
/// ```
pub