
On Thu, Jul 26, 2018 at 4:23 AM, Cristian Morales Vega <cristian@samknows.com> 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