I have an async fn that returns a type, and want to implement Drop on that type that calls another async function. It's not clear how to do this, and I can't find anything in the docs. The most illuminating article I found is Asynchronous Destructors by withoutboats, but I don't really understand the reasoning, or where this feature is at.
Asked
Active
Viewed 4,358 times
7
Shepmaster
- 326,504
- 69
- 892
- 1,159
Matt Joiner
- 106,562
- 103
- 351
- 513
-
3The point of the article is precisely to said that it's not currently possible. And propose a possible solution, but AFAIK it doesn't exist yet. – Stargateur Jan 17 '20 at 06:47
2 Answers
5
It's not clear how to do this, and I can't find anything in the docs
That's because it's not possible; there is no "async Drop". Drop must be synchronous.
See also:
Shepmaster
- 326,504
- 69
- 892
- 1,159
0
I've implemented an async drop using CancellationTokens for a struct we use in our testing.
Note: This is currently just used in our test code, I wouldn't recommended it for any production code without some serious testing.
struct TestObj {
drop_token: CancellationToken,
dropped_token: CancellationToken
}
impl TestObj {
pub async fn new() -> Self {
let drop_token = CancellationToken::new();
let dropped_token = start_drop_watcher(&drop_token).await;
Self {
drop_token,
dropped_token
}
}
async fn start_drop_watcher(drop_token: &CancellationToken) -> CancellationToken {
let drop_child = drop_token.child_token();
let dropped_token = CancellationToken::new();
let dropped_child = dropped_token.child_token();
tokio::spawn(async move {
while !drop_child.is_cancelled() {
tokio::time::sleep(Duration::from_millis(100)).await;
}
// Do async cleanup logic here (probably with a timeout)
dropped_token.cancel();
});
dropped_child
}
}
impl Drop for TestObj {
fn drop(&mut self) {
self.drop_token.cancel();
while !self.dropped_token.is_cancelled() {
std::thread::sleep(Duration::from_millis(100));
}
}
}
It's also important you run your tests with multi-threading or this won't work.
#[tokio::test(flavor = "multi_thread")]
fn it_does_a_thing() {
assert!(true);
}
Dan
- 2,128
- 18
- 28