Ale*_*mer 5 c++ boost boost-asio boost-coroutine
我继承了一个正在boost 1.75上工作的代码库。此代码在 boost 1.75 上运行没有问题:
using CompletionTokenType = boost::asio::yield_context;
using FunctionType = void(boost::system::error_code);
using AsyncResultType = boost::asio::async_result<CompletionTokenType, FunctionType>;
using HandlerType = typename AsyncResultType::completion_handler_type;
[[maybe_unused]] ResultOrErrorType
read(CompletionTokenType token, StatementType const& statement)
{
auto handler = HandlerType{token};
auto result = AsyncResultType{handler};
auto const future = handle_.get().asyncExecute(statement, [handler](auto const&) mutable {
boost::asio::post(boost::asio::get_associated_executor(handler), [handler]() mutable {
handler(boost::system::error_code{});
});
});
result.get(); // suspends coroutine until handler called
if (auto res = future.get(); res) {
return res;
} else {
// handle error
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们被迫迁移到boost 1.82async_compose ,随之而来的是使用/的必要性async_initiate(据我所知)。
代码必须更改为以下混乱。
shared_ptrout,self因为给定的回调是复制回调的asyncExecutea 。std::function可悲的是,与以前self不同,它是不可复制的。handler[[maybe_unused]] ResultOrErrorType
read(CompletionTokenType token, StatementType const& statement)
{
auto future = std::optional<FutureWithCallbackType>{};
auto init = [this, &statement, &future]<typename Self>(Self& self) {
future.emplace(handle_.get().asyncExecute(statement, [sself = std::make_shared<Self>(std::move(self))](auto&& data) mutable {
auto executor = asio::get_associated_executor(*sself);
asio::post(executor, [data = std::move(data), sself = std::move(sself)]() mutable {
sself->complete(std::move(data));
});
}));
};
auto res = asio::async_compose<CompletionTokenType, void(ResultOrErrorType)>(init, token, boost::asio::get_associated_executor(token));
if (res) {
return res;
} else {
// handle error
}
}
Run Code Online (Sandbox Code Playgroud)
这个新代码在大多数情况下都可以正常工作,但最终在输入后会卡住async_compose。我没有看到路径中的任何日志handle error,并且通常假定数据库代码可以正常工作(来自多个其他测试)。调用中始终会触发一个回调asyncExecute。
上面的代码稍微简化了。例如,在 MacOS 上,上面的代码按原样工作,但在 Linux(gcc) 上,我们需要向内部添加一个显式工作对象post,否则应用程序将崩溃。另外,在 MacOS 上,可以sself->complete在不使用 a 包装的情况下进行调用post,但在 Linux 上,这又会导致应用程序崩溃。
所有这些都表明这段代码有些不太正确。请帮助我了解我们做错了什么。任何想法/指示将不胜感激。
如果有办法让旧代码再次运行,这也是一个可行的解决方案。然而,我无法做到这一点,因为completion_handler_type即使 boost 1.82 的文档声称仍然公开它,它似乎已经消失了。
| 归档时间: |
|
| 查看次数: |
165 次 |
| 最近记录: |