如何让boost::asio::awaitable避免初始挂起以安全传递引用?
让Boost.Asio协程避免初始挂起以安全传递引用
Boost.Asio的awaitable协程默认会在启动时立即挂起,但确实能通过**热启动(hot-start)**机制跳过初始挂起,确保引用类型参数在首次co_await前安全有效。
实现方法
1. 使用带自动启动的完成令牌
Boost.Asio提供了支持热启动的co_spawn重载,通过asio::use_awaitable_t<>::with_auto_start作为完成令牌,协程会在创建后立即执行,直到遇到第一个co_await才挂起。示例代码:
#include <boost/asio.hpp> #include <boost/asio/co_spawn.hpp> #include <boost/asio/detached.hpp> using namespace boost::asio; awaitable<void> write_large_message(const LargeMessage& msg) { // 这段同步代码会在协程启动时立即执行,无需等待首次co_await auto serialized = msg.serialize(); co_await async_write(socket, buffer(serialized), use_awaitable); } int main() { io_context ctx; tcp::socket socket(ctx); // 初始化socket逻辑... LargeMessage big_msg; // 用with_auto_start实现热启动,避免初始挂起 co_spawn(ctx, write_large_message(big_msg), use_awaitable_t<>::with_auto_start(detached)); ctx.run(); }
2. 热启动的核心逻辑
你参考的微软博客核心内容翻译如下:
C++标准规定协程默认初始挂起,但多数异步框架都提供了绕过机制。热启动让协程创建后立即进入执行状态,直到碰到第一个需要等待的异步操作(
co_await表达式)才挂起。这样,函数参数的引用在协程启动后的同步执行阶段始终有效,不会出现悬空问题。
关键注意点
- 热启动只改变初始执行行为,后续
co_await仍会正常挂起,不影响协程的异步特性。 - 首次
co_await前的同步代码会在调用co_spawn的线程上立即执行,需注意线程安全。 - 若异步阶段仍需使用该引用,必须保证对象生命周期覆盖整个异步等待周期,不能仅依赖热启动。
内容的提问来源于stack exchange,提问作者bustus_primus
相关产品推荐
相关产品推荐

