std::future 是C++11 的一个模板类,提供了一种用于访问异步操作结果的机制。可以用来获取异步任务的结果,因此可以把它当成一种简单的线程间同步的手段。
设想这样的情况,你希望一个线程进行工作A,同时你在做一些其他的工作,你希望在某个特定的时间获取那个工作A的结果。在c++11,这个可以轻松被 std::future 实现。而由于它是一个模板类,可以返回任何类型的结果。
1 | std::future<Result> fut = std::async(std::launch::async, []() {return A();}); |
用法说明
std::future 对象通常由某个 Provider 创建,你可以把 Provider 想象成一个异步任务的提供者,Provider 在某个线程中设置共享状态的值,与该共享状态相关联的 std::future 对象(通常在另外一个线程中)调用 std::future::get() 获取该值。如果共享状态的标志不为 std::future_status::ready,则调用 get() 会阻塞当前的调用者,直到 Provider 设置了共享状态的值,get() 返回异步任务的返回值或发生的异常。
创建
std::future 的拷贝构造函数和普通赋值操作是被禁用的,只提供了默认的构造函数和 move 构造函数。默认构造函数构造的对象没有共享状态,因此它是无效的,但是可以通过移动赋值的方式将一个有效的future 值赋值给它。
一个有效的 std::future 对象通常由以下三种 Provider 创建,并和某个共享状态相关联。
std::async()函数std::promise::get_future(),为promise类的成员函数std::packaged_task::get_future(),为packaged_task的成员函数
1 | bool test(int d); |
成员函数
bool valid()检查共享状态的有效性,返回当前的
future对象是否与共享状态关联。一旦调用了std::future::get()函数,再调用此函数将返回false。void wait()- 等待共享状态就绪
- 如果共享状态尚未就绪(即未返回或发生异常),则该函数将阻塞调用的线程直到就绪
- 当共享状态就绪后,则该函数将取消阻塞并void返回
std::future_status wait_for(std::chrono::duration span)- 在指定的时间内等待共享状态就绪
- 如果共享状态尚未就绪,则该函数将阻塞调用的线程直到就绪或已达到设置的时间
- 返回
std::future_status:ready/timeout/deferred
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17void test(int d)
{
std::this_thread::sleep_for(std::chrono::seconds(d));
}
int main()
{
std::future<bool> fut = std::move(std::async(test, 1));
auto start = std::chrono::steady_clock::now();
auto future_status = fut.wait_for(std::chrono::seconds(2));
auto end = std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
std::cout << "waited for : " << elapsed_seconds.count() << "s\n";
auto result = fut.get();
}输出:
1
waited for : 1.00856s
std::future_status wait_until(std::chrono::time_point point)- 在指定的时间点前等待共享状态准备就绪
- 如果共享状态尚未就绪,则该函数将阻塞调用的线程直到就绪或已达到指定的时间点
- 返回
std::future_status:ready/timeout/deferred
_Res get()- 当共享状态就绪时,返回存储在共享状态中的值(或抛出异常)
- 如果共享状态尚未就绪,则该函数将阻塞调用的线程直到就绪,相当于
wait()再get() - 当共享状态就绪后,则该函数将取消阻塞并返回释放其共享状态,这使得
future对象不再有效,因此对于每一个future共享状态,get()函数最多应被调用一次 std::future<void>::get()不返回任何值,但仍等待共享状态就绪并释放它
std::shared_future<_Res> share()- 返回一个
std::shared_future对象,该对象获取future对象的共享状态。future对象将不再有效。
- 返回一个
简单例子
1 |
|
std::shared_future
shared_future 与 future 类似,但是允许多个线程等待同一个共享状态。 shared_future 既支持移动操作也支持拷贝操作,而且多个 shared_future 对象可以引用相同的共享状态,还允许多次检索共享状态下的值(多次调用 get() )。
shared_future 可以通过某个 future 对象隐式转换,或者通过 std::future::share() 显示转换,无论哪种转换,被转换的那个 std::future 对象都会变为 not-valid.
std::launch
该枚举类型主要是在调用std::async 设置异步任务的启动策略的。
std::async的原型:
1 | std::async(std::launch::async | std::launch::deferred, f, args...) |
std::launch::async表示在调用
async函数的时候就开始创建新线程。std::launch::deferred表示延迟调用,在调用
future中的wait()或者get()函数时,才执行入口函数。(实际上,并没有创建新线程,只是在主线程中调用的入口函数)
1 | // async |