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

如何为返回Promise的C++函数实现无阻塞重试机制?

解决方案思路与代码示例

核心逻辑梳理

你的核心问题是要让单次请求对应的promise在多次异步重试后最终完成(成功或失败),关键在于保证promise的生命周期覆盖整个重试流程,同时避免阻塞调用线程。以下是关键思路:

  • 用std::shared_ptr<std::promise<void>>持有promise,确保它在所有重试任务完成前不会被销毁
  • 重试逻辑异步执行,延迟等待放在独立线程中,不阻塞foo的调用线程
  • 每次重试尝试后根据结果决定:成功则完成promise,失败则继续延迟重试,耗尽次数则设置失败异常
  • 多请求场景天然隔离:每个foo调用都会创建独立的promise和重试流程,互相不干扰

代码实现

1. 核心执行函数executeFoo

假设它返回bool表示成功/失败,或通过抛出异常表示错误:

#include <future>
#include <chrono>
#include <thread>
#include <atomic>
#include <stdexcept>

bool executeFoo() {
    // 模拟不稳定步骤:随机失败
    static std::atomic<int> attemptCount = 0;
    if (++attemptCount % 3 != 0) {
        return false;
        // 也可以抛出异常:throw std::runtime_error("Step failed");
    }
    return true;
}

2. 重试工具类Util::Retry

实现异步延迟重试,支持指数退避延迟,且保证promise仅被完成一次:

namespace Util {
    template<typename Func>
    void Retry(int maxRetries, std::chrono::milliseconds initialDelay, Func&& func, std::shared_ptr<std::promise<void>> promise) {
        auto completed = std::make_shared<std::atomic<bool>>(false);
        int currentRetry = 0;
        auto currentDelay = initialDelay;

        // 定义单次尝试的逻辑
        auto attempt = [&]() mutable {
            if (*completed) return; // 已完成则直接返回,避免重复操作promise

            try {
                if (func()) {
                    *completed = true;
                    promise->set_value(); // 成功:完成promise
                    return;
                }
            } catch (...) {
                // 捕获执行异常,若已无重试次数则设置异常
                if (currentRetry >= maxRetries) {
                    *completed = true;
                    promise->set_exception(std::current_exception());
                    return;
                }
            }

            // 还有重试次数,安排延迟后重试
            if (currentRetry < maxRetries) {
                currentRetry++;
                currentDelay *= 2; // 指数退避延迟,可选调整为固定延迟
                std::async(std::launch::async, [currentDelay, func, promise, completed, attempt]() {
                    std::this_thread::sleep_for(currentDelay); // 延迟在异步线程执行,不阻塞调用方
                    attempt();
                });
            } else {
                *completed = true;
                promise->set_exception(std::make_exception_ptr(std::runtime_error("All retries failed")));
            }
        };

        // 立即执行第一次尝试
        attempt();
    }
}

3. 对外接口foo函数

返回std::future<void>供调用者获取结果(比返回promise更合理,避免暴露内部状态):

std::future<void> foo() {
    auto promise = std::make_shared<std::promise<void>>();
    auto future = promise->get_future();

    // 启动重试:最多3次重试,初始延迟500ms
    Util::Retry(3, std::chrono::milliseconds(500), []() {
        return executeFoo();
    }, promise);

    return future;
}

4. 调用示例

int main() {
    auto future = foo();
    try {
        future.get(); // 等待结果,成功无返回,失败抛出异常
        std::cout << "Foo succeeded after retries" << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Foo failed: " << e.what() << std::endl;
    }
    return 0;
}

关键细节说明

  • promise生命周期:用shared_ptr持有promise,确保所有异步重试任务都能访问到它,直到任务完成
  • 无阻塞延迟:延迟等待放在std::async创建的独立线程中,foo函数调用后立即返回,不会阻塞调用线程
  • 线程安全:每个foo调用生成独立的promise和重试流程,多请求场景下互相隔离,无竞态问题
  • 异常处理:执行过程中抛出的异常会被捕获,最终通过promise传递给调用者的future

内容的提问来源于stack exchange,提问作者bourne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 22:10:00