如何为boost::asio::yield_context设置超时机制?
如何为boost::asio::yield_context调用设置超时(Boost 1.80)
问题背景
基于Boost 1.80,现有如下协程代码:
#include <boost/asio/io_context.hpp> #include <boost/asio/spawn.hpp> void async_func_0(boost::asio::yield_context yield) { async_func_1(yield); } void async_func_1(boost::asio::yield_context) { // 内部包含不可控耗时的IO操作,基于boost::coroutines实现异步 } int main() { boost::asio::io_context ioc; boost::asio::spawn(ioc.get_executor(), &async_func_0); ioc.run(); return 0; }
需要为async_func_1的调用设置超时,超时后无论操作状态如何都返回错误,类似Rust中timeout方法的效果:
use std::time::Duration; use futures_time::FutureExt; async fn func_0() { func_1().timeout(Duration::from_secs(60)).await; } async fn func_1() { } #[tokio::main] async fn main() { tokio::task::spawn(func_0()); }
解决方案
核心思路是在调用目标协程函数的父协程中,启动一个超时定时器的异步等待,同时以子协程方式执行目标函数。当其中任一操作完成时,取消另一操作:目标函数完成则取消定时器,定时器超时则标记操作失败(若目标操作支持取消,可额外取消其IO操作)。
实现代码
1. 封装超时包装函数
可以封装一个通用的超时包装函数,方便复用:
#include <boost/asio/io_context.hpp> #include <boost/asio/spawn.hpp> #include <boost/asio/deadline_timer.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <iostream> template <typename Func> bool with_timeout(boost::asio::yield_context yield, boost::posix_time::time_duration timeout, Func func) { boost::asio::io_context& ioc = yield.get_io_context(); boost::asio::deadline_timer timer(ioc, timeout); bool operation_completed = false; // 启动子协程执行目标函数 boost::asio::spawn(ioc, [&](boost::asio::yield_context inner_yield) { func(inner_yield); operation_completed = true; timer.cancel(); // 操作完成,取消定时器 }); // 等待定时器超时 boost::system::error_code ec; timer.async_wait(yield[ec]); // 如果定时器被取消,说明操作已完成;否则超时 return operation_completed; }
2. 修改调用逻辑
在async_func_0中使用包装函数为async_func_1添加超时:
void async_func_1(boost::asio::yield_context yield) { // 示例:模拟耗时IO操作 boost::asio::deadline_timer timer(yield.get_io_context(), boost::posix_time::seconds(100)); boost::system::error_code ec; timer.async_wait(yield[ec]); if (ec == boost::asio::error::operation_aborted) { std::cout << "async_func_1被取消" << std::endl; } } void async_func_0(boost::asio::yield_context yield) { bool success = with_timeout(yield, boost::posix_time::seconds(60), [](boost::asio::yield_context yield) { async_func_1(yield); }); if (success) { std::cout << "操作成功完成" << std::endl; } else { std::cerr << "操作超时" << std::endl; // 可选:取消async_func_1中未完成的IO操作(如果有句柄的话) } } int main() { boost::asio::io_context ioc; boost::asio::spawn(ioc.get_executor(), &async_func_0); ioc.run(); return 0; }
关键说明
- 子协程与定时器竞争:通过
spawn创建子协程执行async_func_1,同时启动定时器异步等待,两者并行执行。 - 取消机制:目标操作完成时主动取消定时器,避免不必要的超时触发;定时器超时后,若目标操作未完成,可根据需求取消其内部IO操作(需持有操作对象句柄)。
- 错误传递:若
async_func_1内部的IO操作支持取消,超时后取消操作会让yield返回boost::asio::error::operation_aborted错误,可在async_func_1中处理该错误。
内容的提问来源于stack exchange,提问作者unegare
相关产品推荐
相关产品推荐

