or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing
xxxxxxxxxx
Sabrina Jewson's Async Drop article (Async deep dive 2022-06-23)
tags:
deep-dive
https://sabrinajewson.org/blog/async-drop
Notes during reading
Niko's notes
it seems like cancellation already is quite a bit like pthread-kill, though it's a question of degree. That is, I feel like having potential cancellation at "every await point" often means you just have to be very thoughtful about things you expect to happen on cancellation regardless.
To me the question really comes down controlling the scope of cancellation – i.e., how can we be sure that when a task is cancelled, all the tasks that are interacting with it, especially sharing mutable state, are also cancelled.
I think if you're careful about that (and perhaps you have some specially designated cases of shared state that is expected to surive cancellation, for which you use destructors), it's not so hard to manage.
it's not only
=.await
, it's also all control flow operations like return, break, and continue – and (most notably)?
.agreed, though there are subtle capabilities here that I think we should think about how to preserve :)
Hmm, I might be missing something here, I'm not sure how this works. Aborting in Rust corresponds to dropping – if we ignore synchronous drops for the moment, and just assume all drops are asynchronous (which this post seems to do, which I think is fine), then I guess this corresponds to delaying when the async drop itself runs?
Or is the idea that the async dtor for a future will run the async … I guess I can imagine injecting a failure or something but having the Drop continue running. Seems messy.
Hmm, I am not convinced of this at all. I guess I want to work through the full details of the scenario in question.
It still seems to me like the practical advice is really less about monitoring exactly when your await occurs and more about:
this makes you robust against both await and panic, as a benefit.
Hmm, this is a pretty solid point. I hadn't considered this in full, I think. This kind of returns to the question of "can we make
fn
mean 'maybe async'"? (I still believe we could, up to dyn dispatch).This is an assumption, right? That is, I had assumed that
panic!
would do an "async unroll" if there are async dtors in scope (i.e., we would catch the unwind, do the async drop (possibly awaiting!) and then resume the unwind).Ah, I see, I was missing the point. The point is that panics in sync code could occur.
This isn't really a safety guarantee of Rust regardless – feels like a lot of concern for a pretty artificial example (one that invokes poll manually, for example).
pretty strong point
Tyler's notes
Not quite following the need forOh right, it's talking about relaxing the default to allow async drop, not requiring async drop.Drop
bounds.Gus's notes
Would a correct
Leak
bound now be required when writing unsafe code?nrc's notes
I wonder if async overloading (keyword generics) adds insights here? In particular, that requires choosing between sync/async and handling await somewhat generically. That might make some of the issues around sync/async interactions easier.
Perhaps the fact that await would be implicit means we simply can't do this in a world with explicit awaits?
Drop bounds suck. I think drop and async drop need to be more integrated and this probably requires some kind of magic.
Yosh's notes
"async closures"
There is another distinct benefit to having async closures: different bounds for the closure and the future! Consider the definition of
std::thread::spawn
:The closures is
Send
. The returned valueT
isSend
. But the actual code executing inside the closure is?Send
. This doesn't surface in threads because in non-async Rust the internal structure of a function isn't returned back out in the form of a state machine. But in async Rust, to get the equivalent effect as thestd::thread::spawn
we could imagine the following:There are some issues here because an "async closure" and "closure which returns a future" are not equivalent. But this would enable us to move a closure to a new thread, which guarantees that its contents for the remainder of the execution will not move. Viewed through a lens of "a task is a parallel future", this is a parallelism primitive to operate on
!Send
types in parallel async Rust.Niko: glommio's spawn…
…there's also spawn_local…
Other people's notes
Add yourself a section!
Meeting discussion
Delayed abort
the question is … does
foo
just start "unwinding" and running any in-scope destructors? does it keep running for a while longer?Argument for why to wait until next
Poll::Pending
is at the end of https://sabrinajewson.org/blog/async-drop#delayed-aborthow realistic is this?
How realistic is it that
*x = y
will run some async destructor?We could make you more explicit, but do we want to?
in a sync context?
there are a lot of sync methods that drop stuff (e.g.,
vec.clear
) that want to be asyncanother argument in favor of linear types?
Discussion (Jun 30)
closure semantics
Connection between
async drop
Really needs async overloading!?
linearity
linearity traditionally means "consume exactly once"
niko means by it: cannot be dropped, destructured within its privacy boundary exactly once
functions like
vec::clear
becomeclear_with
, where they take afn(T)
to "consume" the resultadd in async overloading et viola you have
How to prevent synchronous drop of async Drop values in generic code?
nrc: How would we think about this if it were anything other than Drop? / Should we try to focus on drop in a special way instead of just another trait? This seems to be leading us down async versions of traits and so on and it feels like maybe it's a wrong path. Something like
defer
might be useful here.tmandry: What about spawning async destructors as new tasks? Could we have a generic
block_on
in the environment that always worked?nrc: We can catch "async drop in sync context" at runtime and panic/abort.
Seems like because of the nature of Drop being built-in, the "genericity over async" you need becomes infectious throughout all code.
Can we adapt regular sync functions to work in async? Not in general, because
await
points are cancellation points and we shouldn't introduce those silently.yosh: But for async Drop specifically, can we make it uncancellable? We might be able to do this, and it could let us adapt sync functions only for the purpose of running async Drop.
nrc: If we go to that trouble we should introduce non-cancellable futures generally.
yosh: Use cases?
nrc: Interop with C++, Structured concurrency,
tmandry: Heard sentiment expressed that "cancel on await" is confusing
yosh: I have too, but when I dug deeper I found it was something different. Need to see examples – usually it's
select
nrc: Would be good to understand C# people's case for this