我正在使用asio将代码从boost 1.65.1迁移到1.70.0。 有一个使用boost_asio_handler_invoke_helpers :: invoke的代码,它似乎不能像以前的版本那样工作。
我在github上发现了此问题https://github.com/boostorg/asio/issues/79,解释了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]
这意味着没有在正确的执行上下文中恢复堆栈式协程。
答案 0 :(得分:0)
我当前的解决方法是通过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));
}