本文主要讲解C++11/14/17中所提供的应用于多线程编程中的Task机制。
Task可由如下几部分取得
- std::async
- std::packaged_task
- std::promise和std::future
而本文主要讲解std::promise和std::future相关的内容。
std::promise和std::future通过一个数据管道进行交流,可以将std::promise看作生产者,std::future看作消费者,其两者形成如下的方式交互
1 std::promisestd::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异常。
2 std::futurestd::future本身是一个模版类,且其是不可拷贝对象, 可类比std::unique_ptr, 对其所管理的资源具有独占权。
通过std::future,你可以
- 从std::promise获得相应的值
- 询问std::promise是否将值设置为可用
- 等待std::promise的通知。这个等待可以设置一个相对时间间隔或者一个绝对时间
- 创建一个共享的future(std::shared_future)
std::future提供了如下主要接口
share() // 返回一个std::shared_future get() // 从数据管道获得一个值或者异常 valid() // 检查共享状态是否有效,当调用完get接口后,该函数返回false wait() // 等待结果 wait_for() // 等待结果,这个接口会等待一个时间间隔,其返回值为std::future_status wait_until() // 等待结果,该接口会等待到一个绝对时间点,返回值为std::future_status3 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: 接口被延迟执行,也即还未开始
4 示例代码本部分代码部分来自《C++ Concurrency in Action》,其具体示例如下所示
#include#include #include #include void setval(std::promise & 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 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进行相应的构建。
上述相应的输出如下所示
5 总结fut get value: set value 0 not perimted
本文总结了std::promise和std::future的相关概念及其使用。std::promise和std::future一般需要成对出现,用于构建C++多线程中Task。
std::promise和std::future不需要锁等同步措施,其内部本身进行了相应的同步,其使用比mutex要简单方便。



