c++ promise 使用详解
std::promise
-
头文件
#include <future>
。 -
类模板,定义如下:
template<class R> class promise; // 空模板 template<class R> class promise<R&>; // 非 void 特化,用于在线程间交流对象 template<> class promise<void>; // void 特化,用于交流无状态事件
-
作用:
- 提供了存储值或者异常的机制,一般用于在一个线程中设置值或异常,并在另一个线程中获取这些值或异常;
- 与 future 配对使用,通过 promise 的 set_value、set_exception 等方法可以设置一个值或异常,只要设置好,future 即准备就绪,此时可以在另一个线程中通过 future 的 get、wait 方法获取这个值或异常;
- 可实现简单的线程间通信机制:等待数据的线程在 future 上阻塞,而提供数据的线程利用配对的 promise 设定关联的值,使 future 准备就绪;
-
使用方法:
- 创建一个 promise 对象,并通过 get_future() 方法获取与该 promise 关联的 future 对象;
- 在一个线程中执行异步操作,并在合适的时候,通过 set_value() 或 set_exception() 方法设置结果或异常;
- 在另一个线程中,通过 future 的 get() 方法获取结果或等待异常的发生;
-
注意事项:
- 如果 promise 在被销毁时仍未设置值,保存的数据将由异常代替;
- promise 和 future 只能用于一次性的值传递。一旦调用了 set_value() 或 set_exception(),之后就不能再次设置值或异常;
- future 只容许一个线程等待结果,若要让多个线程等待同一个目标事件,则需改用 shared_future;
std::promise 成员函数
get_future
:返回配对的 future 对象,只能调用一次。set_value
:原子的设置值,并使 future 进入就绪状态。set_value_at_thread_exit
:原子的设置值,只有在调用该方法的线程结束并且所有线程局部对象被销毁后,future 才会进入就绪状态。set_exception
:设置异常,并使 future 进入就绪状态。set_exception_at_thread_exit
:设置异常,只有在调用该方法的线程结束并且所有线程局部对象被销毁后,future 才会进入就绪状态。
使用示例
#include <vector>
#include <thread>
#include <future>
#include <numeric>
#include <iostream>
#include <chrono>
void add(int a, int b, std::promise<int>&& promise)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
// 设置值,并使 future 就绪
printf("thread, set result\n");
promise.set_value(a + b);
}
int main()
{
std::promise<int> promise;
auto future = promise.get_future();
std::thread t(add, 1, 100, std::move(promise));
printf("main, wait result\n");
printf("main, get result %d\n", future.get());
t.join();
return 0;
}