2

Given a coroutine spawn into..

void my_coroutine(asio::yield_context yield) {
    system::error_code ec;
    my_wrapper(yield[ec]);
    if (ec) {
        // something went wrong
        return;
    }
    ...
}

void my_wrapper(asio::yield_context&& yield) {
    asio::async_read(..., yield);  // any asio async call
    if (ec) {
        // something went wrong
        return;
    }
    ...
}

In the wrapper function, it's not possible to get access to ec from the passed yield context. So how can this be resolved?

1 Answers1

0

What do you want to /do/ with the ec? You CAN get access is precisely the same way as your my_coroutine already shows:

void my_wrapper(asio::yield_context&& yield) {
    system::error_code ec;
    asio::async_read(..., yield[ec]);  // any asio async call
    if (ec) {
        // something went wrong
        return;
    }
    ...
}

If you mean you wanted to make an async operation that is composable, see this pattern:

Basic example:

template <typename Token>
auto async_meaning_of_life(bool success, Token&& token)
{
#if BOOST_VERSION >= 106600
    using result_type = typename asio::async_result<std::decay_t<Token>, void(error_code, int)>;
    typename result_type::completion_handler_type handler(std::forward<Token>(token));

    result_type result(handler);
#else
    typename asio::handler_type<Token, void(error_code, int)>::type
                 handler(std::forward<Token>(token));

    asio::async_result<decltype (handler)> result (handler);
#endif

    if (success)
        handler(error_code{}, 42);
    else
        handler(asio::error::operation_aborted, 0);

    return result.get ();
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    Yes, it's along the lines of your composable example, which I did find before posting this question, so that the error code propagates up through my_wrapper. I went so far as to port the example but ran into a deeply nested exception on execution. If this is the right way, I shall try again and see if I can isolate the problem. – Serenity Now Feb 28 '20 at 17:32
  • 1
    After another go, I did get composable example working. The nested exception was due to the lifecycle of the object ending while the handler used in the async_wait() call is still on the queue. I'm not quite sure how to resolve that issue. Normally the handler will hold a smart pointer to deal with lifecycle issues, but it's not my handler in this case, it's a coroutine yield context. – Serenity Now Feb 28 '20 at 23:05