You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:55:45