本文主要讲解C++11/14/17中所提供的应用于多线程编程中的Task机制。
Task可由如下几部分取得
而本文主要讲解std::promise和std::future相关的内容。
std::promise和std::future通过一个数据管道进行交流,可以将std::promise看作生产者,std::future看作消费者,其两者形成如下的方式交互

std::promise本身是一个模版类,通过std::promise可以像数据管道中设置value,异常和相应的通知信息。
std::promise提供了如下接口
- get_future() // 返回相应的future
-
- set_value() // 设置一个相应的值
-
- set_exception() // 设置一个异常
-
- set_value_at_thread_exit() // 设置一个值,当线程退出时,promise使数据管道中相应值的状态变为ready
-
- set_exception_at_thread_exit()
如果std::promise设置值或者异常超过一次,那么会抛出std::future_error异常。
std::future本身是一个模版类,且其是不可拷贝对象, 可类比std::unique_ptr, 对其所管理的资源具有独占权。
通过std::future,你可以
std::future提供了如下主要接口
- share() // 返回一个std::shared_future
-
- get() // 从数据管道获得一个值或者异常
-
- valid() // 检查共享状态是否有效,当调用完get接口后,该函数返回false
-
- wait() // 等待结果
-
- wait_for() // 等待结果,这个接口会等待一个时间间隔,其返回值为std::future_status
-
- wait_until() // 等待结果,该接口会等待到一个绝对时间点,返回值为std::future_status
由上述知,future的wait_for和wait_until接口的返回值为std::future_status. 在C++11标准中,该值定义如下
- enum class future_status {
-
- ready,
- timeout,
- deferred
- };
其相应的描述如下所示
ready: 数据管道中的结果已经ready,也即可用
timeout: 数据管道中的数据不可用,且wait等待时间已经到达
deferred: 接口被延迟执行,也即还未开始
本部分代码部分来自《C++ Concurrency in Action》,其具体示例如下所示
- #include <iostream>
- #include <future>
- #include <exception>
- #include <thread>
-
- void setval(std::promise<int>& p ,int a) {
- try {
- if (a == 0) {
- throw std::runtime_error("set value 0 not perimted");
- } else {
- // 设置相应的值
- p.set_value(a);
- }
- } catch(...) {
- // 设置异常,std::current_exception捕获当前异常
- p.set_exception(std::current_exception());
- }
- }
-
- int main() {
- std::promise<int> prom;
- auto fut = prom.get_future();
-
- std::thread t1(setval, std::ref(prom), 0);
- try {
- std::cout << "fut get value: " << fut.get() << "\n";
- } catch(std::exception& ptr) {
- std::cout << ptr.what() << "\n";
- }
-
- t1.join();
- return 0;
- }
注意:在linux平台需要加上 -lpthread进行相应的构建。
上述相应的输出如下所示
fut get value: set value 0 not perimted
本文总结了std::promise和std::future的相关概念及其使用。std::promise和std::future一般需要成对出现,用于构建C++多线程中Task。
std::promise和std::future不需要锁等同步措施,其内部本身进行了相应的同步,其使用比mutex要简单方便。