|
Boost Users : |
Subject: Re: [Boost-users] [Asio/Beast] Any non-obvious reasons for no bind_executor_and_allocator?
From: Vinnie Falco (vinnie.falco_at_[hidden])
Date: 2018-12-20 06:24:23
On Wed, Dec 19, 2018 at 9:37 PM Sorin Fetche <sorin.fetche_at_[hidden]> wrote:
> And this is what I have in mind:
>
> https://github.com/sorf/cpp-playground/blob/master/source/asio_echo.cpp#L45
Have you considered writing a base class which takes ownership of the
user's completion handler and has the necessary hooks? Then you can
simply derive from it in your function-level class declaration to get
all the hooks. Such a base class might look like this:
template<class Handler, class Derived>
class operation_base
{
template<class T, class Executor>
friend struct boost::asio::associated_executor;
Handler handler_;
protected:
Handler const&
handler() const noexcept
{
return handler_;
}
Handler&
handler() noexcept
{
return handler_;
}
public:
operation_base(operation_base&&) = default;
operation_base(operation_base const&) = default;
operation_base& operator=(operation_base&&) = delete;
operation_base& operator=(operation_base const&) = delete;
explicit
operation_base(Handler&& handler)
: handler_(std::move(handler))
{
}
explicit
operation_base(Handler const& handler)
: handler_(handler)
{
}
using allocator_type =
boost::asio::associated_allocator_t<Handler>;
allocator_type
get_allocator() const noexcept
{
return boost::asio::get_associated_allocator(handler_);
}
template<class Function>
friend
void asio_handler_invoke(Function&& f, operation_base* op)
{
using boost::asio::asio_handler_invoke;
asio_handler_invoke(f, std::addressof(op->handler_));
}
friend
bool asio_handler_is_continuation(operation_base* op)
{
using boost::asio::asio_handler_is_continuation;
return asio_handler_is_continuation(
std::addressof(op->handler_));
}
};
namespace boost {
namespace asio {
template<class Handler, class Derived, class Executor>
struct associated_executor<
operation_base<Handler, Derived>, Executor>
{
using type = typename
associated_executor<Handler, Executor>::type;
static type get(operation_base<Handler, Derived> const& op,
Executor const& ex = Executor()) noexcept
{
return associated_executor<
Handler, Executor>::get(op.handler_, ex);
}
};
} // asio
} // boost
Disclaimer: Untested.
The class uses CRTP in order for the associated_executor
specialization to be selected when passing the derived type.
Regards
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net