Moving Boost forward: Asio, coroutines, and maybe even modules
Apr 10, 2025It’s been an exciting quarter over here. Both old-but-refreshed and brand new projects are flourishing in the Boost ecosystem, making today a really exciting moment to contribute to it.
using std::cpp 2025: a tale of coroutines, timeouts and cancellation in Asio
I had the pleasure of speaking at using std::cpp 2025, the biggest C++ conference in Spain. I even had Bjarne Stroustrup himself among the audience!
The talk was focused on how to write simple but effective asynchronous Asio code. Asio is almost two decades old, yet it keeps improving. Since Boost 1.86, code like this is legal:
// Write a message over a socket, and set a timeout to the operation
co_await asio::async_write(sock, asio::buffer(buff), asio::cancel_after(20s));
My talk addressed the mechanisms that power this kind of code, together with many tips gathered by making mistakes while working on Boost.MySQL and related projects. The slides and code snippets I used can be found here, and a recording of the talk will be available soon.
I’ve also updated the servertech chat project, a chat application with a server powered by Boost libraries. It now uses most of the features that I talked about during the talk, including timeouts and C++20 coroutines.
Since the project was using asio::yield_context
, I wrote a small benchmark and found
out that C++20 coroutines were ~10% faster. This might not be the case for all projects, though.
C++20 modules and Boost
I’ve led an initiative to natively support C++20 modules in Boost. The ultimate goal is to enable the user write code like:
import boost.mp11;
using L1 = boost::mp11::mp_list<int, float, int, float>;
The point of the prototype is to be as complete as possible.
I firmly believe that just writing the module units (i.e. the boost_mp11.cppm
file)
is far from enough. This is essentially shipping untested code to the user.
Additionally, building modules is not trivial, specially when there are
complex dependency chains. For this reason, the prototype also includes:
- CMake files to build and install the modules, compatible with today’s Boost CMake infrastructure.
- Running the library’s entire test suite with modules enabled.
- CI scripts to automate running these tests.
I’ve fully migrated Boost.Mp11 (as a representative of header-only libraries) and Boost.Charconv (representing compiled ones). I’ve found a myriad of problems, including compiler bugs, but the result is functional. Compile times wins are really significant - building mp11’s testsuite with modules took only a fourth of the time it takes with headers.
We haven’t merged any of this yet, since it relies on CMake’s experimental features, and there are still many compiler bugs to be fixed.
I’ve summarized my findings in this article.
While working in Charconv, I found some problems unrelated to modules and helped the author fix them.
Boost.MySQL benchmarks
When you use Boost.MySQL, it’s logical to ask yourself “is this much slower than the official drivers?”. Spoiler alert: it’s as fast as libmysqlclient and libmariadb, and even faster under some of the benchmarks.
I didn’t have the data to answer this question until recently, since there are no standard benchmarks to measure this. I’ve designed four benchmarks that focus on the protocol implementation. This includes reading both small and big rows, big batches of rows and using statements with big parameters. Full information available here.
While I’m pretty satisfied with the results, I’ve also identified some points where performance could be improved. These will be addressed in the near future.
Boost.MySQL new features and maintenance
Per user request, I’ve added any_connection::connection_id()
, equivalent
to mysql_thread_id()
in the official API. This allows using KILL
statements
to cancel queries.
I’ve also improved safety by detecting the violation of some preconditions
and issuing errors rather than incurring in undefined behavior. For example,
attempting to start an asynchronous operation in an any_connection
while
another one is outstanding is no longer UB:
// Since Boost 1.88, this is no longer UB.
// The second operation will fail with client_errc::operation_in_progress
conn.async_execute("SELECT 1", r1, [](...) {});
conn.async_execute("SELECT 1", r2, [](...) {});
I’ve fixed some other minor bugs and made some improvements to the docs. The most remarkable is the addition of a [fully-fledged HTTP server example] (https://github.com/boostorg/mysql/tree/07200f17c28293e910151abbc46d22eeff944384/example/3_advanced/http_server_cpp20) that uses C++20 coroutines. I’m in the process of writing the equivalent using callbacks, for users that prefer them.
Boost.Decimal review
Another exciting submission. As usual, I contributed to it by integrating it
into Boost.MySQL, to parse DECIMAL
types.
Next steps
I’m preparing a Postgres library that I aim to submit to Boost on the long run. It’s still in a very early state. I intend to make it similar to Boost.MySQL, but exposing the protocol interface as a public API. More on this next quarter!