TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

C++20: Building a Thread-Pool with Coroutines

122 pointsby MichaEilerabout 4 years ago

6 comments

tele_skiabout 4 years ago
Really nice write up! I'm excited to see more coroutine tutorials and guides come out, I think this C++20 feature has huge potential to make C++ easier to use over the next decade. I will also say I was a bit surprised to see libcoro linked in the article! I'm glad you found it useful but I need to give most of the credit to Lewis Baker's cppcoro as well -- I learned most of what I implemented into libcoro from his fantastic repository and then tuning the coroutine primitives to how I'd want to use the library for an HTTP web server. I just generally find there is no better way to truly learn a difficult concept than to roll your own version.
评论 #27253225 未加载
secondcomingabout 4 years ago
I&#x27;ll admit I find coroutines difficult to grok. It seems to me that &#x27;callback hell&#x27; is turning into &#x27;coroutine hell&#x27;. The only plausible use-case I can see is enabling functionality similar to that of Python&#x27;s `yield`.<p>Does threadpool::thread_loop() not have to check if the popped coroutine is suspended before attempting to resume it?<p>Are they really more efficient than normal callbacks when doing async?
评论 #27250859 未加载
评论 #27253203 未加载
评论 #27251666 未加载
ptrabout 4 years ago
Does anyone know when Coroutines are expected to show up in compilers without enabling experimental flags?
评论 #27255618 未加载
评论 #27252969 未加载
sannysanoffabout 4 years ago
I used similar thing, baked on top of cppcoro library (wonderful thing). My application is heavily threaded with hundreds of thousands of short-lived micro-tasks, it&#x27;s interpreter of highly-parallel expressions, and values are large matrices containing expressions, so it&#x27;s highly parallelizable.<p>I moved to C++ coroutines from composable futures (CF) library that had few thread pool implementations if memory serves (and before CF all was written with callback hell). CF out of the box had extra CPU overhead because internal implementation was not efficient enough for my use, too much templates and copying when switching tasks. Also, spawned tasks had to reference shared pointers in user space (my app code), and unneeded frequent shared pointers copying added unneeded overhead.<p>I rewrote CF implementation later completely, so before coroutines my app used CF API extensively, but with stuff reimplemented, however shared pointers copying was something still far from perfection.<p>In addition to that I had some abstraction (like async&#x2F;await&#x2F;spawn&#x2F;wait_all) on top of CF API, so transformation of application code was not painful. I had to rewrite synchronization primitives to use mutexes which came with cppcoro, and change my own internal scheduler to use some other new primitives.<p>I was afraid that storing local variable in coroutines frames (instead of stack frames) would affect performance, but for some reason it did not.<p>I also expected compilation time to increase, but for some reason it mostly did not. Probably template expansion takes all time, so coroutines code transformation fades in comparison.<p>Since then I stopped using C++ coroutines .<p>I dropped it for following reason:<p>1) unable to debug. Debugger does not have access to local variables, or I cannot enable it. Reference time point: around 9 months ago. Also, stack traces. They are missing, and of course, no help from tools. You have core file, go figure.<p>2) g++ support was missing in the early days when i employed coroutines (clang 9 was just released), but even clang 10 compiler produced wrong code, when using suspended lambda functions. I use lambdas a lot, and as suspended functions spoil the code base, lambdas inevitably become spoiled too. So, it was just occasional SIGSEGV or wrong values. There was a workaround to move 100% of the lambda body to a separated function and then call it from lambda, but it destroys all lambda beauty.<p>I moved to chinese libgo (can be found on github). I don&#x27;t use syscall interceptors it offers, I just use cooperative scheduler it provides, along with synchronization primitives it offers. It&#x27;s stackful cooperative multitasking which keeps all yummy things. And yes, it seemingly performs slightly better in my case. And yes, i had to patch it slightly.<p>TLDR: dropped c++ stackless coroutines in favor of stackful coroutines (cooperative stack switching), what a relief!
评论 #27253384 未加载
评论 #27253139 未加载
评论 #27253568 未加载
sys_64738about 4 years ago
GO style co-routines and native JSON support would pretty much consign GO to history, IMO.
评论 #27252075 未加载
评论 #27256498 未加载
cletusabout 4 years ago
C++20 coroutines confuse me. Like it&#x27;s not clear to me what problem they solve.<p>For the last few years I&#x27;ve been doing Hack (Facebook&#x27;s PHP fork) professionally and async-await as cooperative multitasking is pervasive. IMHO it&#x27;s a really nice model. Generally speaking, I&#x27;ve come around to believing that if it ever comes down to you spawning your own thread, you&#x27;re going to have a Bad Time.<p>Go&#x27;s channels are another variant of this.<p>The central idea in both cases is that expressing dependencies this way is often sufficient and way easier to write than true multithreaded code.<p>C++20 coroutines don&#x27;t seem to solve this problem as best as I can tell.<p>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&#x27;t know.
评论 #27251505 未加载
评论 #27251697 未加载
评论 #27251408 未加载
评论 #27251568 未加载