A Design Space Exploration of Async/Await
21 days ago
- Many languages use async/await to make concurrent programs resemble straight-line code, known as straight-line asynchrony.
- Despite common rationale, async/await implementations vary significantly across languages, with four different outputs from seven runtimes for a simple pseudocode program.
- Key design dimension: Eagerness (hot vs. cold starts) determines whether an async function starts immediately or waits until awaited.
- Nine design dimensions identified, grouped into Start of Life (Eagerness, Suspension), End of Life (Extent, Reference Strength, Destruction, Propagation), and Cancellation (Awareness, Direction, Persistence).
- Extent and Destruction choices explain differing outputs: Swift uses Dynamic Extent with Cancelled Destruction (prints AC), while Trio uses Dynamic Extent with Awaited Destruction (prints ABC).
- Each dimension involves trade-offs in performance, memory, ergonomics, and semantics; no universally right or wrong choices.
- A formal semantics on a core calculus was developed to precisely model and trace execution differences across languages.