C++多线程:future
std::future
在介绍promise
和packaged_task
时多次提到future
,现在详细介绍该类型
std::future
用来获取异步任务的结果,是一种线程间同步的方式,通常由某个Provider创建,Provider在某个线程中设置共享状态的值,与该共享状态相关联的future对象使用std::future::get()
获取
一个有效的future对象通常由以下三种Provider创建,并和某个共享状态关联
std::promise
std::package_task
std::async()
构造函数
- 默认构造函数
由future()noexcept;
std::future
默认构造函数构造的future对象是无效的,除非当前的future对象被移动赋值为另一个有效的future对象 - 拷贝构造函数
被禁用,不可拷贝future(const future&)=delete;
- 移动构造函数
future(future&&)noexcept;
future的拷贝构造和拷贝赋值被禁用,只允许移动拷贝和移动赋值,如下:
std::future<int> fut;
fut= std::async(func);
成员函数
-
std::future::share()
返回一个shared_future对象,此时的future对象已经不再关联共享状态,即变为无效std::future<int> fut= std::async(func); std::shared_future<int> shared_fut= fut.share(); std::cout<<"value:"<<shared_fut.get();
-
std::future::get()
有以下三种形式T get() R& future<R&>::get() void future<void>::get()
若共享状态不为
ready
,则该函数会阻塞当前线程,直到Provider设置了共享状态的值(状态变为ready
),则返回共享状态中的值 -
std::future::valid()
检查当前future对象是否有效,即是否与某个共享状态相关联 -
std::future::wait()
等待与当前future对象相关联的共享状态标志变为ready
若共享状态不为ready
,则该阻塞当前线程,直到共享状态变为ready
std::future<int(int)> fut= std::async(tsk); fut.wait();
-
future_status std::future::wait_for(const chrono::duration<Rep,Period>&)const;
设置等待的时间段,若该时间段结束,共享状态仍没有被Provider设置为ready
,则当前线程被阻塞,该函数返回如下状态:future_status::ready
共享状态标志已经变为ready
,即Provider设置了共享状态的值future_status::timeout
超时,在一段时间内共享状态标志未变为ready
future_status::deferred
共享状态包含一个deferred()
示例如下:
std::cout<<"checking..."<<std::endl; std::chrono::milliseconds span(1000); while(fut.wait_for(span)==std::future_status::timeout){ std::cout<<'.'; }
-
future_status std::future::wait_until(const chrono::time_point<Clock,Duration>&)const;
设置一个系统绝对时间,返回如下状态:future_status::ready future_status::timeout future_status::deferred
std::shared_future
与std::future
类似,但是std::shared_future
允许拷贝,多个shared_future对象可以共享一个共享状态
shared_future可以通过future对象隐式转换,或通过std::future::share()
显示转换,转换后,被转换的对象变为无效
构造函数
- 默认构造函数
shared_future()noexcept;
- 拷贝构造函数
shared_future(const shared_future&);
- 移动构造函数
shared_future(shared_future&&)noexcept;
从future对象构造的重载形式
shared_future(future<T>&&)noexcept;
成员函数
operator=()
get()
valid()
wait()
wait_for()
wait_until()
std::async
template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type> async(Fn&&, Args&&...);
template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type> async(launch, Fn&&, Args&&...);
第一个函数未指定异步任务的启动策略,详见std::launch
枚举类型
启动策略函数可以为launch::async()
,launch::deferred
及二者的按位或
launch::async
异步任务会在另一个线程中调用,并通过共享状态返回异步任务的结果launch::deferred
异步任务将会在共享状态被访问时调用
std::future_error
类型原型
class future_error:public logic_error;
继承自C++标准异常体系的logic_error
其他与std::future
相关的枚举类型
enum class future_errc;
enum class future_status;
enum class launch;
std::future_errc
类型 | 取值 | 说明 |
---|---|---|
broken_promise |
0 | 与共享状态相关联的std::promise 对象在传递值之前被销毁 |
`future_already_retrieved | 1 | 与共享状态相关联的值已经被Provider获取,即调用了future::get() |
promise_already_satisfied | 2 | std::promise 对象已经对共享状态传递了值 |
no_state | 3 | 无共享状态 |
std::future_status
主要用在std::future
(std::shared_future
)中的wait_for()
或wait_until()
中的
类型 | 取值 | 说明 |
---|---|---|
ready |
0 | 共享状态标志 |
timeout |
1 | 在指定时间内共享状态标志仍没有变为ready |
deferred |
2 | 共享状态包含了deferred() |
std::launch
主要用在std::async()
中,设置异步任务的启动策略
类型 | 取值 | 说明 |
---|---|---|
async |
0 | asynchronous异步任务会在另一个线程中调用,并通过共享状态返回结果 |
deferred |
1 | deferred异步任务将会在共享状态被访问时调用,即延时deferred调用 |
示例如下:
#include <iostream>
#include <future>
#include <chrono>
#include <thread>
void do_print_ten(char c, int ms) {
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
std::cout << c;
}
}
int main() {
std::cout << "with launch::async:\n";
std::future < void >foo = std::async(std::launch::async, do_print_ten, '*', 100);
std::future < void >bar = std::async(std::launch::async, do_print_ten, '@', 200);
// async "get" (wait for foo and bar to be ready):
foo.get();
bar.get();
std::cout << "\n\n";
std::cout << "with launch::deferred:\n";
foo = std::async(std::launch::deferred, do_print_ten, '*', 100);
bar = std::async(std::launch::deferred, do_print_ten, '@', 200);
// deferred "get" (perform the actual calls):
foo.get();
bar.get();
std::cout << '\n';
return 0;
}
async
future头文件下,有个async类
用于执行异步任务
int func(int i){
return i+1;
}
auto res= std::async(func,5);
cout<<res.get();