Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use error codes with C++20 Coroutines i.e. awaitables with Boost ASIO

Lets say for example I have a boost::asio::steady_timer timer that I want to async wait on with boost::asio::steady_timer::async_wait. In the old way I get errors as code parameter in my completion handler i.e. my lambda like

timer.async_wait([](const auto &boost_error) {
            //check boost_error
        });

With Co routines I am able to co_await when using boost::asio::use_awaitable as

co_await timer.async_wait(boost::asio::use_awaitable);

However the error handling has changed: In order to catch errors, like an canceled timer, I have to wrap my co_await in a try/catch block.

Can I get boost to let me await on the async operation but giving me the error as a code, like

 std::variant<void, error_code> = co_await timer.async_wait(boost::asio::use_awaitable);

?

like image 203
Superlokkus Avatar asked Oct 24 '25 16:10

Superlokkus


1 Answers

Close: as_tuple(use_awaitable) works almost exactly like that:

Live On Compiler Explorer

#include <boost/asio.hpp>
#include <boost/asio/experimental/awaitable_operators.hpp>
#include <iostream>
namespace asio = boost::asio;
using namespace std::chrono_literals;
using namespace asio::experimental::awaitable_operators;

asio::awaitable<void> timer(auto duration) {
    auto [ec] = co_await asio::steady_timer{co_await asio::this_coro::executor, duration}.async_wait(
        as_tuple(asio::use_awaitable));
    std::cout << "Wait for " << (duration / 1.s) << "s: " << ec.message() << std::endl;
};

int main() {
    asio::io_context ioc;
    asio::co_spawn(ioc, timer(3s) || timer(1500ms), asio::detached);

    ioc.run();
}

Prints:

Wait for 1.5s: Success
Wait for 3s: Operation canceled

Alternative adaptors: asio::redirect_error and asio::as_single

like image 56
sehe Avatar answered Oct 27 '25 06:10

sehe