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

C++中如何检查std::promise的结果是否已设置?

问题解答

截至C++20,std::promise确实没有提供直接检查是否已设置值的成员函数。针对你遇到的多线程回调重复触发、重复调用set_value抛异常的问题,这里有几种可行的替代方案:

1. 封装带原子状态标记的安全Promise

最可靠且性能友好的方式是给std::promise搭配一个原子布尔标记,封装成工具类来避免重复设置值。原子操作能保证多线程下的状态同步,且不会引入额外的异常开销:

#include <future>
#include <atomic>

template<typename T>
class SafePromise {
public:
    void set_value(const T& value) {
        // 原子CAS操作,确保只有第一次调用能成功设置值
        bool expected = false;
        if (_is_set.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) {
            _promise.set_value(value);
        }
    }

    std::future<T> get_future() {
        return _promise.get_future();
    }

private:
    std::promise<T> _promise;
    std::atomic<bool> _is_set{false};
};

在你的回调中使用这个类:

SafePromise<int> safe_promise;

void c_library_callback(int result) {
    // 只有第一次调用会真正设置promise的值
    safe_promise.set_value(result);
}

主线程逻辑不变:等待future拿到结果后调用C库的取消订阅接口。这种方式把状态检查和设置封装在一起,后续代码变更时只要依赖这个工具类,就能降低出错概率。

2. 利用std::future的状态间接判断(局限场景)

如果你能在回调线程中安全访问到绑定的std::future,可以通过wait_for判断future是否已就绪,间接推断promise是否被设置:

// 注意:需用std::shared_ptr保证future在多线程中可安全访问
bool is_promise_set(std::shared_ptr<std::future<int>> future_ptr) {
    return future_ptr->wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}

void c_library_callback(int result, std::shared_ptr<std::future<int>> future_ptr) {
    if (!is_promise_set(future_ptr)) {
        // 需确保回调能访问到对应的promise对象
        promise.set_value(result);
    }
}

但这种方式有明显局限:如果主线程已经调用过future.get(),wait_for也会返回ready,此时无法区分是已设置值还是已消费值,仅适用于特定场景。

3. 捕获std::future_error(最简方案)

虽然你希望避免异常,但std::future_error属于预期内的异常,且C++标准库对这类异常的实现开销很低。如果不想额外封装工具类,可以直接捕获异常:

std::promise<int> promise;

void c_library_callback(int result) {
    try {
        promise.set_value(result);
    } catch (const std::future_error& e) {
        // 仅忽略"promise已被设置"的错误,其他异常重新抛出
        if (e.code() != std::future_errc::promise_already_satisfied) {
            throw;
        }
    }
}

这种方案代码量最小,适合快速解决问题,且仅在重复设置时触发异常,不会影响正常流程。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:00:23