Live data from Hacker News

Looking at Unity made me understand the point of C++ coroutines

mropert.github.io

111–120 of 190 posts

Re: Looking at Unity made me understand the point of C++ coroutines

#111
post #51

Earlier quoted context omitted.

C++ destructors and exception safety will likely wreak havoc with any "simple" assembly/longjmp-based solution, unless severely constraining what types you can use within the coroutines.

Not really. I've done it years ago. The one restriction for code inside the coroutine is that it mustn't catch (...). You solve destruction by distinguishing whether a couroutine is paused in the middle of execution or if it finished running. When the coroutine is about to be destructed you run it one last time and throw a special exception, triggering destruction of all RAII objects, which you catch at the coroutine…

> mustn't catch (...)

You could use the same trick used by glibc to implement unstoppable exceptions for POSIX cancellation: the exception rethrows itself from its destructor.

Re: Looking at Unity made me understand the point of C++ coroutines

#112

Not an expert in game development, but I'd say the issue with C++ coroutines (and 'colored' async functions in general) is that the whole call stack must be written to support that. From a practical perspective, that must in turn be backed by a multithreaded event loop to be useful, which is very difficult to write performantly and correctly. Hence, most people end up using coroutines with something like boost::asio,…

[flagged]

Re: Looking at Unity made me understand the point of C++ coroutines

#113
post #9

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...

People love to complain about Rust async-await being too complicated, but somehow C++ manages to be even worse. C++ never disappoints!

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.

Re: Looking at Unity made me understand the point of C++ coroutines

#114

Earlier quoted context omitted.

It doesn't seem like a clear win to me. The only "assembly" required with std::future is creating the associated promise and using it to signal when that async step is done, and the upside is a nice readable linear flow, as well as ease of integration (just create a thread to run the state machine function if want multiple in parallel). With the coroutine approach using yield, doesn't that mean the caller needs to de…

You are describing a single async step, not a state machine. "Create a promise, set it when done", that's one state. A real async state machine has N states with transitions, branching, error handling, and cleanup between them. > "The only 'assembly' required is creating the associated promise" Again, that is only true for one step. For a state machine with N states you need explicit state enums or a long chain of .t…

I only mentioned co_yield() since that's what the article was (ab)using, although perhaps justifiably so. It seems the coroutine support was added to C++ in a very flexible way, but so low level as to be daunting/inconvenient to use. It needs to have more high level facilities (like Generators) built on top.

What I was thinking of as a state machine with using std::future was a single function state machine, using switch (state) to the state specific dispatch of asynch ops using std::future, wait for completion then select next state.

Re: Looking at Unity made me understand the point of C++ coroutines

#115

Earlier quoted context omitted.

> From a practical perspective, that must in turn be backed by a multithreaded event loop to be useful Multithreaded? Nope. You can do C++ coroutines just fine in a single-threaded context. Event loop? Only if you're wanting to do IO in your coroutines and not block other coroutines while waiting for that IO to finish. > most people end up using coroutines with something like boost::asio Sure. But you don't have to.…

I use asio at work for coroutine. It's one of the most opaque library I've ever used. The doc is awful and impenetrable. The most helpful resource about it is a guy on stackoverflow (sehe). No idea how to get help once SO will have closed

Ask Claude Code to write a manual for it.

Re: Looking at Unity made me understand the point of C++ coroutines

#116
post #40

More broadly the dimension of time is always a problem in gamedev, where you're partially inching everything forward each frame and having to keep it all coherent across them. It can easily and often does lead to messy rube goldberg machines. There was a game AI talk a while back, I forget the name unfortunately, but as I recall the guy was pointing out this friction and suggesting additions we could make at the prog…

This is more evident in games/simulations but the same problem arises more or less in any software: batch jobs and DAGs, distributed systems and transactions, etc. This what Rich Hickey (Clojure author) has termed “place oriented programming”, when the focus is mutating memory addresses and having to synchronize everything, but failing to model time as a first class concept. I’m not aware of any general purpose progr…

> I’m not aware of any general purpose programming language that successfully models time explicitly

Step 1, solve "time" for general computing.

The difficulty here is that our periods are local out of both necessity and desire; we don't fail to model time as a first class concept, we bring time-as-first-class with us and then attempt to merge our perspectives with varying degrees of success.

We're trying to rectify the observations of Zeno, a professional turtle hunter, and a track coach with a stopwatch when each one has their own functional definition of time driven by intent.

Re: Looking at Unity made me understand the point of C++ coroutines

#117

Earlier quoted context omitted.

People love to complain about Rust async-await being too complicated, but somehow C++ manages to be even worse. C++ never disappoints!

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.

Languages like Swift do manage to make it much simpler. The culture guiding Rust design pretty clearly treats complexity as a goal.

Re: Looking at Unity made me understand the point of C++ coroutines

#118
post #9

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...

People love to complain about Rust async-await being too complicated, but somehow C++ manages to be even worse. C++ never disappoints!

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.

Re: Looking at Unity made me understand the point of C++ coroutines

#119

Earlier quoted context omitted.

People love to complain about Rust async-await being too complicated, but somehow C++ manages to be even worse. C++ never disappoints!

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.

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...

[2] https://trio.readthedocs.io/en/stable/

Re: Looking at Unity made me understand the point of C++ coroutines

#120

You can roll stackful coroutines in C++ (or C) with 50-ish lines of Assembly. It's a matter of saving a few registers and switching the stack pointer, minicoro [1] is a pretty good C library that does it. I like this model a lot more than C++20 coroutines: 1. C++20 coros are stackless, in the general case every async "function call" heap allocates. 2. If you do your own stackful coroutines, every function can suspend…

As an x-gamedev, suspect/resume/stackful coroutines made them too heavy to have several thousand of them running during a game loop for our game. At the time we used GameMonkey Script: https://github.com/publicrepo/gmscript That was over 20 years ago. No idea what the current hotness is.

Several thousand? What were you using them for? Coroutines' main utility is that they let you write complex code that pauses and still looks sensible, so for games, you'd typically put stuff like the behavior of an NPC in a coroutine. If you have thousands of things to put each in its own coroutine, they must have been really, really simple stuff. At that point, the cost of context switching can become significant.
Post reply on HN