c++ - boost_asio_handler_invoke_helpers::invoke 是否仍然是在 boost asio 1.70 中调用完成处理程序的受支持方式?

标签 c++ boost-asio

我正在使用 asio 将代码从 boost 1.65.1 迁移到 1.70.0。 有一个使用 boost_asio_handler_invoke_helpers::invoke 的代码,它似乎不像以前的版本那样工作。

我发现了这个问题 https://github.com/boostorg/asio/issues/79在 github 上解释了 executor_binder 是如何工作的。所以在这种情况下,旧的 asio_handler_invoke 函数似乎不再起作用。

class callback_service {
public:
    void run() {
        if (callback_) callback_();
    }

    void subscribe(std::function<void(void)> callback) {
        callback_ = std::move(callback);
    }

private:
    std::function<void(void)> callback_;
};

template <typename CompletionToken>
auto async_wait_callback(callback_service& service, CompletionToken&& token)
{
    return boost::asio::async_initiate<CompletionToken, void(void)>(
        [] (auto&& completion_handler, callback_service& s) {
            s.subscribe([h=std::move(completion_handler)] () mutable {

                // Is this still worked in 1.70 ?
                boost_asio_handler_invoke_helpers::invoke(h, h);
            });
        },
        token, std::ref(service));
}

BOOST_AUTO_TEST_CASE(test_async_wait_callback)
{
    boost::asio::io_context ioc;
    auto work = boost::asio::make_work_guard(ioc);

    callback_service service;

    boost::asio::spawn(ioc, [&] (boost::asio::yield_context yield) {
        const auto initiate_thread_id = std::this_thread::get_id();

        boost::asio::post(ioc, [&] {
            // call the completion handler from another thread.
            std::thread t([&] {
                service.run();
            });
            t.join();
        });

        async_wait_callback(service, yield);

        // Check if we resume in the correct execution context.
        BOOST_CHECK_EQUAL(initiate_thread_id, std::this_thread::get_id());
        ioc.stop();
    });

    ioc.run();
}

测试代码因该错误而失败

Running 1 test case...
error: in "test_async_wait_callback": check initiate_thread_id == std::this_thread::get_id() has failed [10912 != 26444]

这意味着堆栈协程没有在正确的执行上下文中恢复。

最佳答案

我当前的解决方法是通过 get_associated_executor 调度旧回调。

template <typename CompletionToken>
auto async_wait_callback(callback_service& service, CompletionToken&& token)
{
    return boost::asio::async_initiate<CompletionToken, void(void)>(
        [] (auto&& completion_handler, callback_service& s) {
            s.subscribe([h=std::move(completion_handler)] () mutable {
                auto ex = boost::asio::get_associated_executor(h);
                boost::asio::dispatch(ex, [h=std::move(h)] () mutable {
                   boost_asio_handler_invoke_helpers::invoke(h, h);
                });
            });
        },
        token, std::ref(service));
}

关于c++ - boost_asio_handler_invoke_helpers::invoke 是否仍然是在 boost asio 1.70 中调用完成处理程序的受支持方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57405554/

相关文章:

c++ - 为什么 ChangeWindowMessageFilter 会导致 Qt 崩溃?

c++ - Visual Studio 2010 - 链接 MySQL

c++ - 如何使用 gsl::span 修复 No array to Pointer Decay 警告?

c++ - BOOST-ASIO 阻塞服务器不响应阻塞客户端?

c++ - 使用 boost::signals2::signal 作为处理程序时出错

c++ - boost::asio::ip::tcp::socket::cancel 和 socket::close 之间有什么不同

c++ - 此 switch 语句中的代码味道?

c++ - 在宏之后恢复访问修饰符

c++通过网络发送结构

c++ - boost iostreams : How to create buffered (for reading) TCP stream?