Boost logo

Boost Users :

Subject: Re: [Boost-users] ASIO: custom service which works with spawn/yield
From: Vinnie Falco (vinnie.falco_at_[hidden])
Date: 2018-07-26 13:14:32


On Thu, Jul 26, 2018 at 4:23 AM, Cristian Morales Vega
<cristian_at_[hidden]> wrote:
> By this definition of "completed" shouldn't my sample code be fine?

Actually, running the code under the Visual Studio debugger, I realize
now that there are multiple bugs. First, there is the incorrect
signature passed to async_completion as you noted.

Second, you are using the wrong overload of post. Your code should read:

    boost::asio::post(
        this->get_executor(),
        boost::beast::bind_handler(std::move(init.completion_handler), ec));

The consequence of using the 1-argument version of `post` is that your
completion handler will run on a system_executor rather than the
executor associated with the I/O service of your object. This can be
easily verified in the debugger:

<https://i.imgur.com/BsZYgHM.png>

And finally there is the original problem where there is no
executor_work_guard for the io_context.

> This is not supposed to be a composed operation.

You're right about that, and my apologies for the confusing
terminology. I use "composed operation" to also refer to a particular
style of implementation where a class is written as an invocable
function object and is its own completion handler (disclaimer,
untested code):

    template <class Handler>
    class composed_op
    {
        io_context& ioc_;
        Handler h_;
        executor_work_guard <io_context::executor_type> w_;

    public:
        template <class Deduced>
        composed_op (io_context& ioc, Deduced&& h)
            : ioc_ (ioc)
            : h_ (std::forward<Deduced>(h))
            , w_ (ioc)
        {
            boost::asio::post(ioc_, std::move(*this));
        }

        using allocator_type =
            boost::asio::associated_allocator_t<Handler>;

        allocator_type
        get_allocator() const noexcept
        {
            return (boost::asio::get_associated_allocator)(h_);
        }

        using executor_type =
            boost::asio::associated_executor_t<Handler,
io_context::executor_type>;

        executor_type
        get_executor() const noexcept
        {
            return (boost::asio::get_associated_executor)(h_,
ioc_.get_executor());
        }

        void operator()()
        {
            h();
        }
    };

I know, its a lot.

Thanks


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