3/25/2026 at 11:15:25 AM
Simon Tatham, author of Putty, has quite a detailed blog post [0] on using the C++20's coroutine system. And yep, it's a lot to do on your own, C++26 really ought to give us some pre-built templates/patterns/scaffolds.[0] https://web.archive.org/web/20260105235513/https://www.chiar...
by Joker_vD
3/25/2026 at 4:45:45 PM
People love to complain about Rust async-await being too complicated, but somehow C++ manages to be even worse. C++ never disappoints!by zozbot234
3/25/2026 at 7:36:08 PM
I find C++ coroutines to be well-designed. Most of the complexity is intrinsic because it tries to be un-opinionated. It allows precise control and customization of almost every conceivable coroutine behavior while still adhering to the principle of zero-cost abstractions.Most people would prefer opinionated libraries that allow them to not think about the design tradeoffs. The core implementation is targeted at efficient creation of opinionated abstractions rather than providing one. This is the right choice. Every opinionated abstraction is going to be poor for some applications.
by jandrewrogers
3/26/2026 at 2:49:03 AM
I don’t know if the language is yours, but I think the wording and its intended meaning (the sentence starting with ‘The core implementation…’) may be one of the most concise statements of my personal programming language design ethos. I’m jealous that I didn’t come up with it. I will certainly credit you when I steal it for my WIP language.I will be adding the following to my “Primary Design Criteria” list: The core design and implementation of any language feature is explicitly targeted at the efficient creation of opinionated, composable abstractions rather than providing those abstractions at the language level.
by throwaway17_17
3/25/2026 at 9:15:34 PM
C++ standards follow a tick-tock schedule for complex features.For the `tick`, the core language gets an un-opinionated iteration of the feature that is meant for compiler developers and library writers to play with. (This is why we sometimes see production compilers lagging behind in features).
For the `tock`, we try to get the standard library improved with these features to a realistic extent, and also fix wrinkles in the primary idea.
This avoids the standard library having to rely on any compiler magic (languages like swift are notorious for this), so in practice all libraries can leverage the language to the same extend.
This pattern has been broken in a few instances (std::initializer_list), and those have been widely considered to have been missteps.
by fooker
3/26/2026 at 3:35:30 AM
Regarding your mention of compiler magic and Swift, I don’t know much about the language, but I have read a handful of discussions/blogs about the compiler and the techniques used for its implementation. One of the purported benefits/points of pride for Swift that stood out to me and I still remember was something to the effect of Swift being fundamentally against features/abstractions/‘things’ being built in. In particular they claimed the example of Swift not having any literal types (ints, sized ints, bools, etc) “built in” to the compiler but were defined in the language.I don’t doubt your point (I know enough about Swift’s generic resolution crapshow during semantic analysis to be justified in assuming the worst) but can you think of any areas worth looking into for expansion of the compiler magic issues.
I have a near reflexive revulsion for the kinds of non-composability and destruction of principled, theoretically sound language design that tends to come from compiler magic and shortcuts, so always looking for more reading to enrage myself.
by throwaway17_17
3/26/2026 at 7:58:11 AM
> literal types (ints, sized ints, bools, etc) “built in” to the compiler but were defined in the language.This is actually a good example by itself.
Int is defined in swift with Builtin.int64 IIRC. That is not part of the swift language.
by fooker
3/26/2026 at 8:20:49 AM
Not really, because due to C++'s unsafe first approach, means that workarounds like Pin aren't required.Additionally, for those with .NET background, C++ co-routines are pretty much inspired by how they work in .NET/C#, naturally with the added hurdle there isn't a GC, and there is some memory management to take into account.
Also so even if it takes some time across ISO working processes, there is still a goal to have some capabilities on the standard library, that in Rust's case means "use tokio" instead.
by pjmlp
3/25/2026 at 6:56:22 PM
async is simply a difficult problem, and I think we'll find irreducible complexity there. Sometimes you are just doing 2 or 3 things at once and you need a hand-written state machine with good unit tests around it. Sometimes you can't just glue 3 happy paths together into CSP and call it a day.by 01HNNWZ0MV43FF
3/25/2026 at 7:45:14 PM
Using structured concurrency [1] as introduced in Python Trio [2] genuinely does help write much simpler concurrent code.Also, as noted in that Simon Tatham article, Python makes choices at the language level that you have to fuss over yourself in C++. Given how different Trio is from asyncio (the async library in Python's standard library), it seems to me that making some of those basic choices wasn't actually that restrictive, so I'd guess that a lot of C++'s async complexity isn't that necessary for the problem.
[1] https://vorpus.org/blog/notes-on-structured-concurrency-or-g...
by quietbritishjim
3/26/2026 at 4:12:11 AM
After so wrote the comment below I realized that it really is just ‘um, actually…’ about discussing using concurrency vs implementing it. It’s probably not needed, but I do like my wording so I’m posting it for personal posterity.In the context of an article about C++’s coroutines for building concurrency I think structured concurrency is out of scope. Structured concurrency is an effective and, reasonably, efficient idiom for handling a substantial percentage of concurrent workloads (which in light of your parent’s comment is probably why you brought up structured concurrency as a solution); however, C++ coroutines are pitched several levels of abstraction below where structured concurrency is implemented.
Additionally, there is the implementation requirements to have Trio style structured concurrency function. I’m almost certain a garbage collector is not required so that probably isn’t an issue, but, the implementation of the nurseries and the associated memory management required are independent implementations that C++ will almost certainly never impose as a base requirement to have concurrency. There are also some pretty effective cancelation strategies presumed in Trio which would also have to be positioned as requirements.
Not really a critique on the idiom, but I think it’s worth mentioning that a higher level solution is not always applicable given a lower level language feature’s expected usage. Particularly where implementing concurrency, as in the C++ coroutines, versus using concurrency, as in Trio.
by throwaway17_17
3/26/2026 at 1:16:03 AM
Python's stdlib now supports structured concurrency via task groups[1], inspired by Trio's nurseries[2].by maleldil
3/26/2026 at 12:07:21 PM
Good point. I did carefully say that Trio "introduced" structured concurrency, partly due to this (and also other languages that now use it e.g. Swift, Kotlin).I will say that it's still not as nice as using Trio. Partly that's because it has edge-triggered cancellation (calling task.cancel() injects a single cancellation exception) rather than Trio's level-triggered cancellation (once a scope is cancelled, including the scope implicit in a nursery, it stays cancelled so future async calls all throw Cancelled unless shielded). The interaction between asyncio TaskGroup and its older task API is also really awkward (how do I update the task's cancelled count if an unrelated task I'm waiting on throws Cancelled?). But it's a huge improvement if you're forced to use asyncio.
by quietbritishjim
3/25/2026 at 10:37:07 PM
It's quite simple in Golang.by jujube3
3/26/2026 at 7:07:13 AM
Golang has a GC and that makes a lot of things easier.by menaerus
3/25/2026 at 7:32:48 PM
Languages like Swift do manage to make it much simpler. The culture guiding Rust design pretty clearly treats complexity as a goal.by rafram
3/26/2026 at 3:49:48 AM
C++ is great, coroutines are not. Neither of these are good ways to handle concurrency. You really need a more generalized graph and to minimize threads and context switching. You can't do more than the number of logical cores on a CPU anyway.by CyberDildonics