4 ms·
Who is asking for C++ coroutines and how did we get to C++20 without it?
by monkeyelite 1y ago
Who is asking for C++ coroutines and how did we get to C++20 without it?
- quietbritishjim 1y agoI'm interested in this too. Coroutines in Python are fantastically useful and allow more reliable implementation of networking applications. There is a complexity cost to pay but it's small and resolves other complexity issues with using threads instead, so overall you end up with simpler code that is easier to debug. "Hello world" (e.g., with await sleep(1) to make it non-trivially async) is just a few lines. But coroutines in C++ are so stupendously complicated I can't imagine using them in practice. The number of concepts you have to learn to write a "hello world" application is huge. Surely just using callback-on-completion style already possible with ASIO (where the callback is usually another method in the same object as the current function), which was already possible, is going to lead to simpler code, even if it's a few lines longer than with coroutines? Edit: We have a responsibility as senior devs (those of us that are) to ensure that code isn't just something we can write but that other can read, including those that don't spend their spare time reading about obscure C++ ideas. I can't imagine who in good faith thinks that C++ coroutines fall into this category.
- rhaen 1y agoThe majority of the complexity is in the library/executor, rather than in callers. We have an implementation at my company which is now being widely rolled out and it's a pretty dramatic readability win to convert callback based codes to nearly-straight line coroutine code.
- quietbritishjim 1y agoThat's very promising. Boost ASIO seemed to be the first serious coroutine library for C++ and that seemed complex to use (I'm saying that as a long-time user of its traditional callback API) but that's perhaps not surprising given that it had to fit with its existing API. But then there was a library (I forget which) posted to HN that was supposed to be a clean fresh coroutine library implementation and that still seems more complex than ASIO and callbacks - it seemed like you needed to know practically every underlying C++ coroutine concept. But maybe there just needed to be time for libraries to mature a bit.
- spacechild1 1y agoI was just going to mention ASIO. > and that seemed complex to use Actually. I found it pretty straightforward. I switched from callbacks to coroutines un my personal project and it is a massive win! Now I can write simple loops instead of nested callbacks. Also, most state can now stay in local variables.
- monkeyelite 1y agoThere is another way to write code which lets you write simple loops and isn’t coroutines. Blocking code.
- spacechild1 1y agoSure, but then you need one thread per socket, which has its own set of problems (most notably, the need for thread synchronization). I definitely prefer async + coroutines over blocking + thread-per-socket.
- horizion2025 1y agoJava's new philosophy (in "Loom" - in production OpenJDK now) seems to be virtual threads that are cheap and can therefore be plentiful compared to native threads. This allows you to write the code in the old way without programmer-visible async.
- spacechild1 1y agoOk, but virtual threads still need thread synchronization.
- monkeyelite 1y agowhich isn't a problem unless you are abusing threads. If you avoid synchronization, like javascript then you also don't get pre-emption or parallelism.
- horizion2025 1y agoAs to the complexity: It is complex because it is very low-level. In JavaScript (using that as an example but I suspect Python is the same) they build in async/await keywords such that they are in cahoots with the Promise class. C++ takes a different path where there isn't a built-in Promise class, rather it provides you lower-level primitive you can use to build a Promise class. You can build a library around it, and it will be as simple as in other languages - both for the awaiter and for implementing libraries that you can await on :) But I agree it is really complicated. I remember once in a while thinking "ah it can't really be that complicated" only to dive into it again. It doesn't help that practically any term they use (promise, awaiter etc.) is used differently than in all other contexts I've worked. If you just expect it will be as easy as understand JavaScript async/await/promise you are in for a rude surprise. Raymond Chen has written co-routines tutorials which span three SERIES. Here's a map of those: https://devblogs.microsoft.com/oldnewthing/20210504-01/?p=105178 https://devblogs.microsoft.com/oldnewthing/20210504-01/?p=10... As for how we got to here without: 1) Using large number processes/threads 2) Raw callback oriented mechanisms (with all the downsides) 3) Structured async where you pass in lambda's - benefit is you preserve the sequential structure and can have proper error handlign if you stick to the structure. Downside is you are effectively duplicating language facilities in the methods (e.g. .then(), .exception() ). Stack traces are often unreadable. I. 4) Raw use of various callback-oriented mechanisms like epoll and such, with the cost in code readability etc. and/or coupled with custom-written strategies to ease readability (so a subset of #3 really) With C++ couroutines the benefit is you can write it almost like you usually do (line-by-line sequentially) even though it works asynchronously.