头文件 future
带有允许异步访问特定提供者设置的值的设施的标头,可能在不同的线程中。
这些提供者中的每一个(它们是 promise 或 packaged_task 对象,或对 async 的调用)与未来对象共享对共享状态的访问:提供者使共享状态准备就绪的点与未来对象访问共享的点同步状态。
class template future
future是一个对象,它可以从某个提供者(promise 或 packaged_task 对象,或对 async 的调用)对象或函数中检索值,如果在不同的线程中,则可以正确同步此访问。
“有效”期货是与共享状态关联的未来对象,并通过调用以下函数之一来构造:
- async
- promise::get_future
- packaged_task::get_future
future对象仅在有效时才有用。 默认构造的future对象是无效的(除非assigned了一个有效的future)。
在有效的 future 上调用 future::get 会阻塞线程,直到提供者准备好共享状态(通过为其设置值或异常)。 这样,两个线程可以通过一个等待另一个设置值来同步。
共享状态的生命周期至少持续到与其关联的最后一个对象释放它或被销毁。 因此,如果与future相关联,则共享状态可以在最初获得它的对象(如果有的话)中存在。
// future example
#include <iostream> // std::cout
#include <future> // std::async, std::future
#include <chrono> // std::chrono::milliseconds
// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
for (int i=2; i<x; ++i) if (x%i==0) return false;
return true;
}
int main ()
{
// call function asynchronously:
std::future<bool> fut = std::async (is_prime,444444443);
// do something while waiting for function to set future:
std::cout << "checking, please wait";
std::chrono::milliseconds span (100);
while (fut.wait_for(span)==std::future_status::timeout)
std::cout << '.' << std::flush;
bool x = fut.get(); // retrieve return value
std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n";
return 0;
}
class template std::promise
promise 是一个对象,它可以存储类型 T 的值,以供future对象(可能在另一个线程中)检索,提供同步点。
在构造中,promise 对象与一个新的共享状态相关联,它们可以在该共享状态上存储 T 类型的值或从 std::exception 派生的异常。
可以通过调用成员 get_future 将此共享状态关联到future对象。 调用后,两个对象共享相同的共享状态:
- Promise 对象是异步提供者,预计会在某个时候为共享状态设置一个值。
- future对象是一个异步返回对象,可以检索共享状态的值,如果需要,等待它准备好。
共享状态的生命周期至少持续到与其关联的最后一个对象释放它或被销毁。 因此,如果它也与未来相关联,它可以在最初获得它的promise对象中幸存下来。
1 get_future
返回与对象的共享状态关联的未来对象。
一旦准备好,返回的未来对象可以访问由承诺对象在共享状态上设置的值或异常。
对于每个承诺共享状态,只能检索一个未来对象。
调用此函数后,promise 应在某个时刻使其共享状态准备就绪(通过设置值或异常),否则在销毁时自动准备好包含 future_error 类型的异常(带有 broken_promise 错误条件 )。
2 std::promise::set_value
将 val 存储为共享状态中的值,该状态已准备就绪。
如果与同一共享状态关联的未来对象当前正在等待对 future::get 的调用,它会解除阻塞并返回 val。
void 特化的成员只是使共享状态准备就绪,而不设置任何值。
// promise example
#include <iostream> // std::cout
#include <functional> // std::ref
#include <thread> // std::thread
#include <future> // std::promise, std::future
void print_int (std::future<int>& fut) {
int x = fut.get();
std::cout << "value: " << x << '\n';
}
int main ()
{
std::promise<int> prom; // create promise
std::future<int> fut = prom.get_future(); // engagement with future
std::thread th1 (print_int, std::ref(fut)); // send future to new thread
prom.set_value (10); // fulfill promise // (synchronizes with getting the future)
th1.join();
return 0;
}
class template std::packaged_task
packaged_task 包装了一个可调用元素并允许异步检索其结果。它与 std::function 类似,但将其结果自动传输到未来对象。
该对象内部包含两个元素:
- 存储任务,它是一些可调用对象(例如函数指针、指向成员或函数对象的指针),其调用签名应采用 Args 中类型的参数…并返回 Ret 类型的值。
- 一种共享状态,能够存储调用存储任务(类型为 Ret)的结果,并通过 future 异步访问。
共享状态通过调用成员 get_future 与future对象相关联。 调用后,两个对象共享相同的共享状态: - packaged_task 对象是异步提供者,预计通过调用存储的任务将共享状态设置为就绪。
- future对象是一个异步返回对象,可以检索共享状态的值,如果需要,等待它准备好。
// packaged_task example
#include <iostream> // std::cout
#include <future> // std::packaged_task, std::future
#include <chrono> // std::chrono::seconds
#include <thread> // std::thread, std::this_thread::sleep_for
// count down taking a second for each value:
int countdown (int from, int to) {
for (int i=from; i!=to; --i) {
std::cout << i << '\n';
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Lift off!\n";
return from-to;
}
int main ()
{
std::packaged_task<int(int,int)> tsk (countdown); // set up packaged_task
std::future<int> ret = tsk.get_future(); // get future
std::thread th (std::move(tsk),10,0); // spawn thread to count down from 10 to 0
// ...
int value = ret.get(); // wait for the task to finish and get result
std::cout << "The countdown lasted for " << value << " seconds.\n";
th.join();
return 0;
}