3 ms·
> and is a major source why people dislike Rust's async It's worth mentioning that there is, in fact, no language out there other than Rust that can even do th
by simonask 2mo ago
> and is a major source why people dislike Rust's async
It's worth mentioning that there is, in fact, no language out there other than Rust that can even do this in the first place.
Some languages give the illusion that they support it by boxing the stack frame of async functions and letting a garbage collector deal with the consequences, but that comes with significant drawbacks too (additional GC pressure, heap allocation overhead, requiring a GC in the first place).
You can do it with C++ coroutines, but it's much harder to do correctly than in Rust if you want to maintain any sense of conviction that the system is correct.
The main reason that structured async concurrency would be so awesome to have is that it feels like Rust has the right set of features that could enable it with a set of constraints that are so much more attractive than any other language out there can provide - no overhead, "just works" with no drawbacks.
(For the record, you can actually get pretty far today using primitives like `FuturesUnordered` instead of `tokio::spawn` and similar, but this sidesteps the runtime's scheduler, so YMMV. This basically creates a task-local mini-scheduler for your futures, which may or may not be sufficient.)
- spacechild1 2mo agoC++26 adopted senders/receivers (std::execution) as its official concurrency model, with the explicit aim of supporting structured concurrency. See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p23...
- simonask 2mo agoSkimming the proposal, that looks like the equivalent of the "executor" (scheduler) and "task" (sender) implemented in Rust async runtimes. I could have missed it, but I don't see anything in particular to help with managing structured concurrency? Like, the central challenge is cancellation: In structured concurrency, subtasks spawned from a parent task must finish cancelling before the parent task can be cancelled.
- spacechild1 2mo agohttps://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html#design-cancellation https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p23...
- drysine 2mo ago>You can do it with C++ coroutines, but it's much harder to do correctly than in Rust if you want to maintain any sense of conviction that the system is correct. Could you elaborate on this?
- simonask 2mo agoC++ just lets you pass a reference or pointer from one task's stack to another task or thread, with no assurance that the callee task terminates before the caller's stack is deallocated (i.e. the caller returns before its children terminate). This is a compile error in Rust, and you need unsafe code to achieve it. But then the real power is that you can construct a safe API that lets you do it safely, fully checked at compile time. See `std::thread::scope` in the standard library, or `rayon::scope` if you want an implementation based on thread pools.
- drysine 2mo agoThanks! >See `std::thread::scope` in the standard library, or `rayon::scope` if you want an implementation based on thread pools. These seem to be about multu-threaded code if I got it right, but how does async work?