4 ms·
C++20 coroutines confuse me. Like it's not clear to me what problem they solve. For the last few years I've been doing Hack (Facebook's PHP fork) professionall
by cletus 5y ago
C++20 coroutines confuse me. Like it's not clear to me what problem they solve.
For the last few years I've been doing Hack (Facebook's PHP fork) professionally and async-await as cooperative multitasking is pervasive. IMHO it's a really nice model. Generally speaking, I've come around to believing that if it ever comes down to you spawning your own thread, you're going to have a Bad Time.
Go's channels are another variant of this.
The central idea in both cases is that expressing dependencies this way is often sufficient and way easier to write than true multithreaded code.
C++20 coroutines don't seem to solve this problem as best as I can tell.
It actually seems like C++20 coroutines are closer to Python generators. Is this the case? Or is this a classic case of a camel is a horse designed by committee and the C++ standards committee tried to create primitives to handle these and possibly other use cases? I honestly don't know.
- saurik 5y agoI use them constantly in my work on Orchid, and, FWIW, one of your coworkers--Lewis Baker--was seemingly hired to help champion the standards and work on Folly Coro. I use the feature much the same way I would in, say, JavaScript (doing stuff like "await Fetch(...)" or "await Query(...)"); I honestly am sufficiently confused by your question that I am having a hard time saying much more... the C++ version of this primitive is great because it doesn't have any baggage about "executors" or anything and lets me have complete control over how the task switching happens. You can build generators with the feature, but I almost never do; there are a couple things I wish the C++ people had done with their implementation (which involves a weirdly thick-feeling interface to implement, and which makes it difficult to truly avoid memory allocation)--in particular, including some of Lewis Baker's interests in asynchronous deconstruction, without which I am finding myself often boxed into a corner (though what I really want, honestly, are true "linear" types)--but by and large I love the C++ implementation of this for its complete flexibility.
- boardwaalk 5y agoThey solve exactly the problem you describe; I'm not sure what you're missing. What are you thinking you can't do? I have a project where I've put C++ coroutines on top of libuv and I can do essentially anything I could do in JS/C#/Rust async/await with task/co_await/etc with the imperative style you'd expect. You may have looked at them at too low a level. Check out something like cppcoro to see what you can do. I don't use it myself, but I've stolen a few things, like task<>, which is a pretty core thing that the stdlib does not provide. Goroutines are not cooperative multitasking, by the way, they're non-OS/"green" threads. Until you do something silly like run CPU-bound code that doesn't hit any yield points and you have to put them in yourself (at least the last time I used Go, it's been awhile).
- harikb 5y agoWhile the starvation behavior of cooperative green-threads isn’t ideal as native threads, the idea is that 1. Properly written code will perform well, whether async/await or Go style. 2. Making async easy makes one use it in more places. In additon having caller decide to run something sync or async also makes it way more useful. In Async/await model that can only work if all methods are declared async - very costly in complexity
- jimsimmons 5y agoGood way to put what’s wrong with Python async and probably by extension C++ too. The sync-async in both direction need to be symmetrical for it to make sense. Right now in Python async can interact with Python sync quite comfortably but the opposite direction is a literal black hole. I have had to read up on how sync can interact with async multiple times but I’m still not sure what is the idiomatic way and it always feels like it’s on knife edge even when I get something working. Obviously, the caveat is that I’m just stupid and don’t understand Python async well enough. But I have a feeling that this is common experience
- harikb 5y agoNo, it is not you. https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
- jimsimmons 5y agoThis is the millionth time I’ve come across this post. I always had assumed this post was about Typed / multiple Dispatch for whatever idiotic reason. So glad that this has been well pointed out. Oof big relief
- harikb 5y agoMain problems with async await model is that the callee decides whether something should run sync/async. In goroutines model, caller decides
- Matthias247 5y agoI don't think so. coroutine awaits are just like normal function calls in Go (since all of Go functions are implicitely suspendable). I guess you meant the "go" statement? That is more of a coroutine spawn thing, and this would be a separate function in C++ too.
- harikb 5y ago> since all of Go functions are implicitely suspendable Right. we are saying the same thing about Go. The comparison was with those languages that have explicit async keyword.
- ninepoints 5y agoYou're missing the big idea a bit. Coroutines in C++ can be used to implement generators or goroutines or async/await, etc. They are intended for library authors as a lower level construct. See for example: https://www.jeremyong.com/cpp/2021/01/04/cpp20-coroutines-a-minimal-async-framework/ https://www.jeremyong.com/cpp/2021/01/04/cpp20-coroutines-a-...
- cletus 5y agoI literally said this at the end of my comment about coroutines being a low-level primitive.
- dundarious 5y agoYou raised two hypotheticals and said you honestly don't know if either/both/neither are true. 1. Is it like Python generators? 2. Is it a bad example of design by committee and meant as a set of lower level primitives? GP responded that 2 is correct (but without the sass on design by committee) and that 2 allows for them to implement such things as 1. I think they gave their opinion as to what parts of your hypotheticals are true, and that is a valuable contribution, and very much not the same as just repeating parts of your comment ("I literally said this").