Crouton is a C++20 coroutine runtime library that provides some general purpose concurrency utilities, as well as cross-platform event loops, I/O and networking that work the same way on Mac, Linux, Windows and ESP32 microcontrollers.
The cross-platform support is based on the widely-used libuv, mbedTLS and llhttp libraries. (On Apple platforms it can also use the system Network.framework. On ESP32, where libuv is not supported, it uses lwip and FreeRTOS APIs instead.)
A Coroutine is a function that can return partway through, and then later be resumed where it left off. Knuth wrote about them in the 1960s and they remained a curiosity for a long time, but they've since become widely used under the hood of the "async / await" concurrency model used in languages like JavaScript, C#, Rust, Nim, and Swift. Crouton brings this to C++.
Async/await gives you concurrency without the pitfalls of multithreading. You can write code in a linear fashion, "blocking" on slow operations like I/O (see the example below), but the thread doesn't really block: instead your (coroutine) function is suspended and some other function that's finished blocking can resume. When the I/O completes, your function is resumed transparently at the next opportunity.
How is that better than threads? It's safer and easier to reason about. The only places where concurrency happens are well-marked by the co_await and co_yield keywords. You don't need mutexes or atomic variables, and there are far fewer opportunities for race conditions or deadlocks. (There are performance benefits too: no expensive context switches, less stack usage.)
Detailed documentation is being written.
- 
Coroutine library:
- Useful base classes for implementing new coroutine types
 Future, an asynchronous promise typeGenerator, an iterator implementation based onco_yield-ing valuesCoMutex,CoCondition,Blocker: cooperative equivalents of common sync primitivesAsyncQueue, a producer/consumer queueSelect, a way to await multiple things in parallel- Optional coroutine lifecycle tracking, with debugging utilities to dump all existing coroutines and their "call stacks".
 
 - 
Event loops:
Scheduler, which manages multiple active coroutines on a thread- Round-robin scheduling of multiple active coroutines
 - Suspending a coroutine, then waking it when it's ready
 - Scheduling a function to run on the next event-loop iteration, even on a different thread
 - Scheduling a function to run on a background thread-pool
 
Task, an independently-running coroutine that canco_yieldto give time to othersTimer, repeating or one-shot
 - 
Reactive publish/subscribe framework
- Enables building complex networked data flows out of modular components
 - Intrinsically supports backpressure to manage flow control on sockets
 - Loosely inspired by Apple's Combine framework
 - Double-plus experimental ⚗️
 
 - 
Asynchronous I/O classes:
- DNS lookup
 - File I/O
 - Filesystem APIs like 
mkdirandstat - Abstract asynchronous stream interface
 - In-process pipes
 - TCP sockets, with or without TLS
 - A TCP listener (no TLS support yet)
 - URL parser
 - HTTP client
 - HTTP server (very basic so far)
 - WebSocket client and server
 - BLIP RPC protocol (optional; under separate license.)
 
 - 
Core classes & APIs:
- General-purpose 
ErrorandResult<T>types - Logging, a very compact library with an API inspired by spdlog.
 - Type-safe string formatting, similar to 
std::formatbut with a much lower code footprint. 
 - General-purpose 
 - 
Cross-Platform:
- macOS (builds and passes tests)
- iOS? ("It's still Darwin…")
 
 - Linux (builds and passes test)
- Android? ("It's still Linux…")
 
 - ESP32 embedded CPUs (builds and passes tests. Networking works, but filesystem APIs aren't implemented yet.)
 - Windows (builds, but I don't have any Windows machines to test on. Help wanted!)
 
 - macOS (builds and passes tests)
 
// Simple HTTP client request:
HTTPConnection client("https://example.com");
HTTPRequest req;
HTTPResponse resp = co_await req.sendRequest(req);
cout << int(resp.status()) << " " << resp.statusMessage() << endl;
for (auto &header : resp.headers())
    cout << header.first << " = " << header.second << endl;
ConstBuf body;
do {
    body = co_await resp.readNoCopy();
    cout << string_view(body);
} while (body.len > 0);
cout << endl;See also demo_server.cc, a simple HTTP and WebSocket server.
An example embedded app is at tests/ESP32.
This is new code, under heavy development! So far, it builds with Clang (Xcode 15) on macOS, GCC 12 on Ubuntu, Visual Studio 17 2022 on Windows, and ESP-IDF 5.1.
The tests run regularly on macOS, and occasionally on Ubuntu (though not in CI.) Test coverage is very limited.
APIs are still in flux. Things get refactored a lot.
Important: Make sure you checked out the submodules!
git submodule update --init --recursive
- CMake
 - Clang 15, Xcode 15, or GCC 12
 - zlib (aka libz)
 
- Install Xcode 15 or later, or at least the command-line tools.
 - Install CMake; this is most easily done with HomeBrew, by running 
brew install cmake 
sudo apt-get install g++ cmake cmake-data zlib1g-dev
make
make test
The library is libCrouton, in either the build_cmake/debug/ or build_cmake/release/ directory.
Before first building with Xcode, you must use CMake to build libuv and mbedTLS:
make xcode_deps
You only need to do this on initial setup, or after those submodules are updated.
Then:
- open crouton.xcodeproj
 - Select the 
Testsscheme and Run. - To locate the binaries, choose Product > Show Build Folder In Finder
 
The ESP-IDF component is at src/io/esp32; please see the README for details. A demo app is at tests/ESP32.
- Crouton itself is licensed under the Apache 2 license.
- The files in the subdirectory 
src/io/blip, however, are under the Business Software License since they are adapted from existing BSL-licensed code. These source files are optional and are by default not compiled into the Crouton library. See their README for details and the full license. - The source file 
src/io/URL.cccontains some code adapted from tlsuv, which is Apache 2 licensed. 
 - The files in the subdirectory 
 - Of the third party code in 
vendor/:- Catch2 is licensed under the Boost Software License (but is only linked into the tests)
 - libuv is licensed under the MIT license.
 - llhttp is licensed under the MIT license.
 - mbedtls is licensed under the Apache 2 license.
 - spdlog is licensed under the MIT license.
 
 
- Crouton code by Jens Alfke (@snej)
 - Initial inspiration, coroutine knowledge, starting code: Simon Tatham's brilliant tutorial. Lewis Baker's blog posts have also been helpful.
 - Event loops, I/O, networking: libuv
 - TLS engine: mbedTLS
 - HTTP parser: llhttp
 - Logging: spdlog
 - Unit tests: Catch2
 - Extra inspiration and URL parser: tlsuv