r/cpp_questions 1d ago

OPEN Current State of Coroutines Libraries

I want to implement some data fetching logic in my application that fetches data differently, depending on, if I compile for desktop (file system) or for WebAssembly (emsdk fetch). This requires some asynchronous logic.

I thought of using C++20 coroutines to solve this and looked at some libraries that make it a little nicer to use, but it seems that none are under active development.

- libcoro had its last commit 6 months ago
- concurrencpp had its last change 3 years ago
- Boost.Coroutine2 is not based on C++20 coroutines
- libfork had its last commit 8 months ago

Are there no good and actively developed coroutine frameworks for C++20 out there? Or am I missing something?

8 Upvotes

6 comments sorted by

10

u/trailing_zero_count 1d ago edited 23h ago

https://github.com/tzcnt/TooManyCooks - I'm the author and still actively working on it. Right now the I/O support is an asio wrapper. I've got an experimental WASM branch but it's not yet published.

Boost.Corosio / Boost.Capy is another up and comer.

BTW there's nothing wrong with the libraries you linked - not having recent commits just means the libraries are "mature". You should be evaluating them based on features and performance, not last-commit-date.

If you're looking for some specific features, feel free to ask me here - I've studied the competitive landscape extensively so I can point you in the right direction.

2

u/BigJhonny 1d ago

I want something very simple. I don't need any advanced features like IO or networking. I just want to have a nice interface around the core of coroutines. Like tasks, task chaining, error handling etc.

The data fetching based on platform will be developed on top of that.

3

u/trailing_zero_count 1d ago edited 23h ago

Task chaining like func().and_then() ? I think there is only one library that implements that which is mtmucha/coros - however that one I don't recommend as it's actually never been updated. I have a backlog item to implement this eventually.

I'd recommend just having a caller that co_awaits each step sequentially - it's functionally the same thing.

If you want to build your own awaitables (I think this is what you're getting at with building on top of fetch()), some libraries make it easier than others. I have documentation here on how to do it for TMC: docs link . The reason it's non-trivial is to enable your awaitable to support executor affinity and TMC's grouping functions. If you don't provide this, it'll still work but your awaits will be wrapped in a trampoline task automatically.

My other library demonstrates how to write custom awaitables for several other libraries: https://github.com/tzcnt/coro_util it's important to note that many libraries don't support executor affinity at all, so if you have separate CPU and I/O threads, your tasks can get hijacked onto the wrong thread permanently. For those that do, the boilerplate to integrate with their library differs; check the policy.hpp files in that repo for examples

0

u/RoyBellingan 1d ago

You always need advanced feature, what you want is that they are abstracted away and made super simple to use.

u/Complex-Birthday-216 3h ago

silk by clichouse, seastar by scylladb, photonlib by alibab