什么是std::promise?
std::promise 对象可以保存某一类型 T 的值,该值能被 std::future 对象读取(存在是另一个线程的可能),所以std::promise 提供了一种线程同步的手段。std::promise像一个外卖盒子,不同的线程可以通过这个盒子传递数据。
std::promise的构成
-
基础函数(构造、析构、赋值):
默认构造函数会初始化一个空的共享状态;禁止拷贝构造,同时赋值操作被禁止,只提供了移动构造;另外支持带allocator的构造函数
析构函数:如果有std::future对象关联到同一共享状态,共享状态本身不会被销毁。如果在共享状态就绪前被销毁,则会为共享状态自动准备一个std::future_error异常,并使其处于就绪状态 -
operator=函数:禁用拷贝赋值,但可以移动赋值。
-
swap函数:交换 promise 的共享状态。
-
get_future函数:返回一个与promise对象共享状态关联的std::future对象。当就绪时,std::future对象就可以访问promise对象在共享状态上设置的值或异常。每个promise共享状态仅能被一个std::future对象检索。若调用此函数后,promise应在某个时刻使其共享状态准备就绪(通过设置值或异常),否则一个std::future_error将在销毁时自动准备就绪。
-
set_value函数:即设置共享状态的值,共享状态的标志设置为ready。
-
set_value_at_thread_exit函数:设置共享状态的值,但并不将该共享状态的标志设置为ready,当线程退出时,该promise对象会自动设置为ready。
-
set_exception函数:设置共享状态的异常指针,共享状态的标志设置为ready。
-
set_exception_at_thread_exit函数:设置共享状态的异常指针,但并不将该共享状态的标志设置为ready,当线程退出时,该promise对象会自动设置为ready
代码释义
最简单的作为线程之间传递数据
#include <vector>
#include <thread>
#include <future>
#include <numeric>
#include <iostream>
#include <chrono>
void GetCalcuSum(std::vector<int>::iterator begin, std::vector<int>::iterator end,
std::promise<int> accumulate_promise)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
int total = std::accumulate(begin, end, 0); //自动求和
std::this_thread::sleep_for(std::chrono::milliseconds(500));
accumulate_promise.set_value(total); // 提醒 future
}
void SimpleThreadData() {
// 演示用 promise<int> 在线程间传递结果。
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
std::promise<int> total_promise;
std::future<int> accumulate_future = total_promise.get_future(); //绑定
std::thread work_thread(GetCalcuSum, numbers.begin(), numbers.end(), std::move(total_promise));
//std::future::get() 将等待直至该std::promise共享状态就绪
std::cout << "result=" << accumulate_future.get() << std::endl;
work_thread.join(); // wait for thread completion
}
void SimpleThreadEnd()
{
auto sum_fun_exit = [&](std::vector<int>::iterator begin, std::vector<int>::iterator end,
std::promise<int> &accumulate_promise) {
std::cout << "set_value_at_thread_exit" << std::endl;
//accumulate_promise.set_value_at_thread_exit(1000); // 提醒 future
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
std::cout << "thread_exit" << std::endl;
};
auto sum_fun_value = [&](std::vector<int>::iterator begin, std::vector<int>::iterator end,
std::promise<int>& accumulate_promise) {
std::cout << "set_value" << std::endl;
accumulate_promise.set_value(999); // 对比
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
std::cout << "thread_exit" << std::endl;
};
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
std::promise<int> total_promise;
std::future<int> accumulate_future = total_promise.get_future(); //绑定
std::thread work_thread(sum_fun_exit, numbers.begin(), numbers.end(), std::ref(total_promise));
std::cout << "result=" << accumulate_future.get() << std::endl;
work_thread.join(); // wait for thread completion
}
void SimpleBindOnce()
{
// 演示只能与一个future绑定。
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::promise<int> total_promise;
std::future<int> total_future1 = total_promise.get_future(); //绑定
try {
std::future<int> total_future2 = total_promise.get_future(); //绑定
} catch (const std::future_error& e) {
std::cout << "future_error : " << e.what() << std::endl;
}
}
int main()
{
SimpleThreadEnd();
//SimpleThreadData();
//SimpleBindOnce();
}
结果(对比 set_value_at_thread_exit)