Stream: wg-async-foundations

Topic: async drop


Jake Goulding (Sep 18 2019 at 14:03, on Zulip):

Has there been discussion about some kind of async drop? For example, if you have a database connection that does a COMMIT on drop, that might take time. Drop is sync by nature, which might tie up the future.

My guess is that the answer is "create a bespoke method that does the IO work and you can call .await on it"

simulacrum (Sep 18 2019 at 14:08, on Zulip):

Hm, so I feel like I've seen some discussion about this on internals

simulacrum (Sep 18 2019 at 14:08, on Zulip):

But it does seem like you could do something like rt::spawn(commit()) and then just exit, though that does mean that you will only find out later that the commit didn't go through

simulacrum (Sep 18 2019 at 14:09, on Zulip):

but that seems similar to e.g. File's Drop not panicking on errors and such

Jake Goulding (Sep 18 2019 at 14:12, on Zulip):

I agree with the similarity, which is solved by using an explicit call as well (e.g. sync_all)

Jake Goulding (Sep 18 2019 at 14:12, on Zulip):

like you could do something like rt::spawn(commit())

Do you mean in the Drop::drop implementation?

simulacrum (Sep 18 2019 at 14:33, on Zulip):

yeah

boats (Sep 18 2019 at 19:54, on Zulip):

We've thought about this a fair bit!

boats (Sep 18 2019 at 19:55, on Zulip):

I've sketched threw the design a few weeks ago and made an interesting realization, which I will record here: the problem with something like async fn drop is that the future it returns can contain additional state beyond &mut Self.

boats (Sep 18 2019 at 19:56, on Zulip):

This means that the futures which call the destructor may, for example, not be Send if you introduce !Send state.

boats (Sep 18 2019 at 19:56, on Zulip):

There's absolutely no way to write the bound for "the future returned by T's async destructor, if it has one, is Send"

boats (Sep 18 2019 at 19:57, on Zulip):

T: AsyncDrop implies OutputOf(<T as AsyncDrop>::drop_async): Send, combining several features we don't have, and not pretty

boats (Sep 18 2019 at 19:58, on Zulip):

In the near term, we should probably pursue a poll-based approach: fn poll_drop(self: Pin<&mut Self>) -> Poll<()>. In the long term we could also introduce an async fn version if we feel its needed.

boats (Sep 18 2019 at 19:59, on Zulip):

The poll based approach guarantees that all of the state for the async destructor is contained in the type being destroyed.

boats (Oct 17 2019 at 10:55, on Zulip):

I wrote a blog post about this, and theres now an internals thread: https://internals.rust-lang.org/t/asynchronous-destructors/11127/16

stko (Oct 17 2019 at 12:10, on Zulip):

The desugaring proposed in internals thread is synchronous:

while let Poll::Pending = self.poll_drop_ready(cx) {}
self.drop()

Shouldn't it be something more along the lines of:

poll_fn(self.poll_drop_ready).await;
self.drop()
Last update: Nov 18 2019 at 01:10UTC