Boost logo

Boost Users :

Subject: Re: [Boost-users] [Asio/Beast] Any non-obvious reasons for no bind_executor_and_allocator?
From: Sorin Fetche (sorin.fetche_at_[hidden])
Date: 2018-12-20 17:25:18


On Wed, Dec 19, 2018 at 10:24 PM Vinnie Falco wrote:
>
> On Wed, Dec 19, 2018 at 9:37 PM Sorin Fetche 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?

<snip>

Yes, the base class is a very good idea.
It helps reduce the boilerplate in the composed operation and the risk
of moving `this` before accessing things in it.

Here's how its usage looks like to implement the composed operation:
https://github.com/sorf/cpp-playground/blob/master/source/asio_echo_v2.cpp#L105

\code
    struct internal_state : public state_base {
        /*...*/
        static void async_echo(internal_state&& self) {
            auto read_buffer = asio::buffer(self.echo_buffer);
            self.socket.async_read_some(
                read_buffer,
                self.wrap()([self = std::move(self)](error_code ec,
std::size_t bytes) mutable {
                        if (!ec) {
                            /*...*/
                        } else {
                            self.call_handler(ec, bytes);
                        }
                    }));
        }

        void call_handler(error_code ec, std::size_t bytes) {
            /* Deallocate derived state resources */
            this->call_handler_base(ec, bytes);
        }
\endcode

I still don't like the risk of moving `this` (or `self`) before
members in the derived class are used to initiate the next operation
(e.g. the echo_buffer).

On Wed, Dec 19, 2018 at 10:24 PM Vinnie Falco wrote:
> 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;
<snip>
> template<class Function>
> friend
> void asio_handler_invoke(Function&& f, operation_base* op)
<snip>
> friend
> bool asio_handler_is_continuation(operation_base* op)

It looks like the base class doesn't even need these hooks, at least
not directly.
The object returned by asio::bind_executor and its equivalent for
allocator, which doesn't exist yet, should have them.
I'll take a shot at this in the next version of the example code.

Best 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