std::future
std::future 简介
我们前面介绍的std::thread 是C++11中提供异步创建多线程的工具,只能是异步运行任务,却无法获取任务执行的结果,一般都是依靠全局对象,全局对象在多线程下是及其不安全的,为此标准库提供了std::future类模板来关联线程运行的函数和函数的返回结果,这种获取结果的方式是异步的。
本质上线程支持库。
std::future
C++ 线程支持库 std::future
定义于头文件 <future>
template< class T > class future;(1) (C++11 起)
template< class T > class future<T&>;(2) (C++11 起)
template<> class future<void>;(3) (C++11 起)
类模板 std::future 提供访问异步操作结果的机制:
- (通过 std::async 、 std::packaged_task 或 std::promise 创建的)异步操作能提供一个 std::future 对象给该异步操作的创建者。
- 然后,异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。
- 异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的 std::future 的共享状态(例如 std::promise::set_value )进行。
注意, std::future 所引用的共享状态不与另一异步返回对象共享(与 std::shared_future 相反)。
引用:std::future
示例1
#include <iostream>
#include <future>
#include <thread>
int main()
{
// 来自 packaged_task 的 future
std::packaged_task<int()> task([](){ return 7; }); // 包装函数
std::future<int> f1 = task.get_future(); // 获取 future
//std::cout << "Done!\nResults are: "<< f1.get() << '\n';
std::thread(std::move(task)).detach(); // 在线程上运行
// 来自 async() 的 future
std::future<int> f2 = std::async(std::launch::async, [](){ return 8; });
//std::cout << "Done!\nResults are: " << f2.get() << '\n';
// 来自 promise 的 future
std::promise<int> p;
std::future<int> f3 = p.get_future();
std::thread( [&p]{ p.set_value_at_thread_exit(9); }).detach();
std::cout << "Waiting..." << std::flush;
f1.wait();
f2.wait();
f3.wait();
std::cout << "Done!\nResults are: "<< f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
}
示例2
#include <iostream> // std::cout
#include <future> // std::async, std::future
#include <utility> // std::move
int do_get_value() { return 11; }
int main () {
// 由默认构造函数创建的 std::future 对象,
// 初始化时该 std::future 对象处于为 invalid 状态.
std::future<int> foo, bar;
foo = std::async(do_get_value); // move 赋值, foo 变为 valid.
bar = std::move(foo); // move 赋值, bar 变为 valid, 而 move 赋值以后 foo 变为 invalid.
if (foo.valid()) {
std::cout << "foo's value: " << foo.get() << '\n';
} else {
std::cout << "foo is not valid\n";
}
if (bar.valid()) {
std::cout << "bar's value: " << bar.get() << '\n';
} else {
std::cout << "bar is not valid\n";
}
return 0;
}