如何为返回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
相关产品推荐
相关产品推荐

