Boost.Asio async_compose高负载下阻塞及版本迁移问题求助
Boost 1.75到1.82迁移后的协程异步代码问题
原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 } }
迁移至Boost 1.82后的修改代码
迁移时认为必须改用async_compose/async_initiate,修改后存在以下情况:
- 传给
asyncExecute的回调是可复制的std::function,而self不可复制,因此将self封装为shared_ptr - 出现回调嵌套的“回调地狱”,失去了协程原本的顺序性代码结构
[[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 } }
遇到的问题
- 新代码多数情况运行正常,但高负载下进入
async_compose后会出现阻塞,无错误日志输出;经测试DB代码正常,asyncExecute的回调始终会触发一次 - 跨平台差异问题:
- macOS可正常运行,Linux(gcc)下需给内部
post添加显式工作对象否则崩溃 - macOS可直接调用
sself->complete,Linux下则需用post包裹否则崩溃
- macOS可正常运行,Linux(gcc)下需给内部
需求
寻求问题原因及解决思路,若能恢复旧代码的运行方式也可;目前尝试恢复旧代码时发现completion_handler_type似乎已不存在,尽管Boost 1.82文档称仍会暴露该类型。
内容的提问来源于stack exchange,提问作者Alex Kremer
相关产品推荐
相关产品推荐

