4 ms·
One advantage of async/await is that its easier to cancel things. For example, this leads to the design pattern where you have multiple futures and you want to
by fvncc 3y ago
One advantage of async/await is that its easier to cancel things. For example, this leads to the design pattern where you have multiple futures and you want to select the one that finishes first and cancel the rest.
In regular threaded programming, cancellation is a bit more painful as you need to have some type of cancellation token used each time the thread waits for something. This a) is more verbose and b) can lead to bugs where you forget to implement the cancellation logic.
- charcircuit 3y ago>In regular threaded programming, cancellation is a bit more painful No, it isn't. Nothing is stopping your threading library from implementing the same thing. It just turns out it is a bad idea to kill threads at random points in time because they may own things like locks. Or in the case of async await doing something that is thought to be atomic.
- Spivak 3y agoYou're describing exactly why it's painful for threads. If you only cancel co-routines at yield points (which unless you do dark magic is the only time you can cancel them) is always safe. A co-routine that yields in the middle of an atomic operation is an oxymoron. Anything can happen before you're scheduled again.
- fvncc 3y agoWell each time you use the await keyword you are saying its a safe point to exit, which is more predictable than killing at random points. Holding locks across await points is an anti-pattern, and Rust at least can give a hint if you try to do that. Async/await implementations will also generally allow you to run cleanup code on cancellation (but the exact mechanism depends on the language). In the end, its about expressing a state machine in a more concise implicit way, which is a suitable level of abstraction for most use cases.
- heavenlyblue 3y ago> One advantage of async/await is that its easier to cancel things. For example, this leads to the design pattern where you have multiple futures and you want to select the one that finishes first and cancel the rest. > In regular threaded programming, cancellation is a bit more painful as you need to have some type of cancellation token used each time the thread waits for something. This a) is more verbose and b) can lead to bugs where you forget to implement the cancellation logic. Yeah of course Rust just makes cancellation so easy by allowing the Futures to be dropped. What about the resources these Futures could have allocated within the context that are not just memory? You are saying it as if async/await somehow solved the whole problem of stack unwinding.
- quietbritishjim 3y agoI think the comment was about async in general, not just Rust (although that's the topic of OP). In Python, cancellation causes an exception to be injected at the await site, which allows it to clean up whatever resources it likes (even if that means making other async calls). If you use Trio or the new TaskGroup in asyncio (inspired by Trio) then an exception leaking out of one task causes the others to be cancelled, and then the task group waits for all tasks to complete (successfully, with exception, or cancelled). It's extremely nice and easy to write reliable programs. In principle, I think many of these ideas could be applied to threaded IO. But I haven't seen it done in practice.
- gpderetta 3y ago> In principle, I think many of these ideas could be applied to threaded IO. That's how POSIX deferred [1] cancellation works. An uncatchable exception is thrown from blocking calls if a thread is requested to terminate. As POSIX is C centered, you can imagine that handling exceptions was never popular, but it should work fine in C++. For some reasons it wasn't added to std::thread though. [1] there is also async cancellation, but friends do not let friends use PTHREAD_CANCEL_ASYNCHRONOUS.
- heavenlyblue 3y ago> In Python, cancellation causes an exception to be injected at the await site, which allows it to clean up whatever resources it likes (even if that means making other async calls). If you use Trio or the new TaskGroup in asyncio (inspired by Trio) then an exception leaking out of one task causes the others to be cancelled, and then the task group waits for all tasks to complete (successfully, with exception, or cancelled). It's extremely nice and easy to write reliable programs. But not in JavaScript.