Does async/await solve a real problem?

Florian Bösch pyalot at
Thu Sep 11 09:29:53 PDT 2014

The problem of code interleaving isn't on a fundamental level (like with
threads). Threads are a very different best, that interlave at random
points in time, and hence require some heavy lifting by the environmnet/OS
to not immediately fall flat.

Cooperative multitasking between I/O primitives is much friendlier. But
still, you can wreck some havoc if you have multiple tasklets running that
modify the same data structure. You won't get a race condition in the
classical sense, but you can still produce garbage data (like say call out
to async inside a loop over an array of which you've cached the length).

However, the exact same breakage applies to await/async, because if you
await inside a loop, of which you've cached the length, and have some other
code modify the array in the meantime... So not really an argument.

On Thu, Sep 11, 2014 at 4:55 PM, Mark S. Miller <erights at> wrote:

> On Thu, Sep 11, 2014 at 7:22 AM, Florian Bösch <pyalot at> wrote:
>> A -> B -> C -> D -> E changes to
>> A -> B -> C -> D -> async E and causes
>> A await -> B await -> C await -> D await -> async E
>> And of course if A, B, C or D is used anywhere else it percolates trough
>> the entire call graph.
>> Trying to protect people from interlaved code execution effects is noble.
> Exactly. Good to see we agree on the implications even if we value these
> outcomes differently.
>> But doing so by introducing a rote thing to type everytime you change the
>> code somewhere underneath is wrong. It's wrong because it breaks logic
>> isolation, it becomes impossible to change part of the library/utiity code
>> without this change affecting all code that uses it. This guarantees that
>> it doesn't happen in practice, because it's too painful to do. It requires
>> the code, that uses other code, to know about the internal behavior of that
>> code.
>> If say, I'd propose a semantic that required you to write "foo" in the
>> code, but just for those pieces of code that contain mentions of "bar", or
>> that reference code that contains "bar" to the Nth degree, you'd accuse me
>> of trying to introduce a purposefully unusable feature. How is await/async
>> not an unusable feature?
> On Thu, Sep 11, 2014 at 7:25 AM, Florian Bösch <pyalot at> wrote:
>> Furthermore, since await is call graph infectious, for those really
>> wanting to use it, it means that before long, await is written before every
>> single function call. Which makes no sense.
> In a purely functional system without side effects of any form (i.e.,
> ignoring even strictness and exceptions), interleaving is harmless, so this
> conclusion is valid. You would indeed safely get better code reuse if you
> placed async/await everywhere, so that instead should have been the default
> in such a language. In fact, since interleaving is harmless, you can
> schedule all computation as you like, including in parallel, lazily,
> eagerly, whatever, without harming correctness. In the absence of side
> effects, we should indeed not have placed a notational burden on
> interleaving points.
> But in an imperative system with synchronous side effects that co-exists
> with interleaving hazards, we also needs a way to protect against such
> hazards. The economy of the communicating event loop model is that each
> turn is implicitly a mutually exclusive atomic transaction -- without
> needing extra notation for synchronization or transaction boundaries.
> The cost of making atomicity cheap is that interleaving points must be
> made explicit. With callbacks, this cost is quite high. Promises reduce
> this cost substantially. async/await further reduces this cost about as far
> as it can be reduced, while still leaving an explicit marker.
> --
>     Cheers,
>     --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list