chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.72k stars 1.19k forks source link

Channel functions don't support type-erased completion handlers #1379

Open anarthal opened 8 months ago

anarthal commented 8 months ago

Hi,

It looks like experimental::channel functions don't support the type-erased any_completion_handler. Minimal reproducible example:

#include <boost/asio/any_completion_handler.hpp>
#include <boost/asio/experimental/channel.hpp>

using boost::system::error_code;
using boost::asio::experimental::channel;
using boost::asio::any_completion_handler;

void erased_fn(
    channel<void(error_code)>& chan,
    any_completion_handler<void(error_code)> h
)
{
    chan.async_receive(std::move(h));
}

Or, in compiler-explorer.

Having a look at the code, the problem seems that channel functions require posting to the passed I/O executor (as in calling asio::require(ex, asio::execution::blocking.never). However, the executor associated to any_completion_handler is any_completion_executor, which doesn't support posting (as opposed to any_io_executor).

Snippet from any_completion_handler:

template <typename... Signatures, typename Candidate>
struct associated_executor<any_completion_handler<Signatures...>, Candidate>
{
  using type = any_completion_executor;

  static type get(const any_completion_handler<Signatures...>& handler,
      const Candidate& candidate = Candidate()) BOOST_ASIO_NOEXCEPT
  {
    return handler.fn_table_->executor(handler.impl_,
        any_completion_executor(std::nothrow, candidate));
  }
};

template <typename... Signatures, typename Candidate>
struct associated_immediate_executor<
    any_completion_handler<Signatures...>, Candidate>
{
  using type = any_completion_executor;

  static type get(const any_completion_handler<Signatures...>& handler,
      const Candidate& candidate = Candidate()) BOOST_ASIO_NOEXCEPT
  {
    return handler.fn_table_->immediate_executor(handler.impl_,
        any_io_executor(std::nothrow, candidate));
  }
};

Use case: I'm using any_completion_handler in Boost.MySQL to reduce compile times. I'm implementing connection pooling in terms of channels, and just found this.

If you can provide me some guidance on how to fix this, I could try to submit a PR.

Many thanks, Ruben.