3 ms·
std::future doesn't give you a state machine. You get the building blocks you have to assemble into one manually. Coroutines give you the same building blocks b
by LatencyKills 7mo ago
std::future doesn't give you a state machine. You get the building blocks you have to assemble into one manually. Coroutines give you the same building blocks but let the compiler do the assembly, making the suspension points visible in the source while hiding the mechanical boilerplate.
This is why coroutine-based frameworks (e.g., C++20 coroutines with cppcoro) have largely superseded future-chaining for async state machine work — the generated code is often equivalent, but the source code is dramatically cleaner and closer to the synchronous equivalent.
(me: ex-Visual Studio dev who worked extensively on our C++ coroutine implementation)
- physPop 7mo agoI feel like thats really oversellign coro -- theres still a TON of boilerplate
- LatencyKills 7mo agoMy response specifically addressed the question of why you might choose one option over the other. Do you believe that std::future is the better option?
- HarHarVeryFunny 7mo agoIt 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 decide when to call it again? With the std::future approach where it's event driven by the promise being set when that state/step has completed.
- LatencyKills 7mo agoYou 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 .then() continuations. You also need to the manage the shared state across continuations (normally on the heap). You need to manage manual error propagation across each boundary and handle the cancellation tokens. You only get a "A nice readable linear flow" using std:future when 1) using a blocking .get() on a thread, or 2) .then() chaining, which isn't "nice" by any means. Lastly, you seem to be conflating a co_yield (generator, pull-based) with co_await (event-driven, push-based). With co_await, the coroutine is resumed by whoever completes the awaitable. But what do I know... I only worked on implementing coroutines in cl.exe for 4 years. ;-)
- HarHarVeryFunny 7mo agoI 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.
- LatencyKills 7mo ago> as to be daunting/inconvenient to use I don't even know how to respond to that. How in the world are you using C++ professionally if you think coroutines are "daunting"? No one uses C++ for it's "convenience" factor. We use it for the power and control it affords. > 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. Uh huh. What about error propagation and all the other very real issues I mentioned that you are just ignoring? Why not just let the compiler do all the work the way it was spec'ed and implemented?
- HarHarVeryFunny 7mo agoSo it's meant to be inconvenient, and that's the only right and proper way?! Sounds more like punishment than software design, but each to their own.
- LatencyKills 7mo agoI get what you’re saying, but you kicked off this thread like an expert — even though you knew you were talking to someone who helped build the very thing you’re critiquing. It’s pretty clear you’ve never built a production-grade async state machine. C++ is designed to provide the plumbing, not the kitchen sink. It’s a language for building abstractions, not handing them to you — though in practice, there’s a rich ecosystem if you’d rather reuse than reinvent. That flexibility comes at the cost of convenience, which is why most new engineers don’t start with C++. What you call “intimidating,” I call powerful. If coroutines throw you off, you’re probably using the wrong language. Last thought — when you run into someone who’s built the tools you rely on, ask them questions instead of trying to lecture them. I would have been more than happy to work through a pedagogical solution with you. /ignored
- sta1n 7mo ago[dead]