C++11 提供了std::future
类模板,future 对象提供访问异步操作结果的机制,很轻松解决从异步任务中返回结果。
在 C++ 标准库中,有两种“期望”,使用两种类型模板实现(这里主要介绍的是唯一期望):
- 唯一期望(
unique futures
,std::future<>
) 实例只能与一个指定事件相关联。 - 共享期望(
shared futures
,std::shared_future<>
) 实例能关联多个事件。
事实上,一个std::future
对象在内部存储一个将来会被某个 provider 赋值的值,并提供了一个访问该值的机制,通过get()
成员函数实现。但如果有人试图在get()
函数可用之前通过它来访问相关的值,那么get()
函数将会阻塞,直到该值可用。
一个有效的std::future
对象通常由以下三种 Provider 创建,并和某个共享状态相关联。Provider 可以是函数或者类,他们分别是:
std::async
函数;std::promise::get_future
,get_future 为 promise 类的成员函数;std::packaged_task::get_future
,此时 get_future为 packaged_task 的成员函数;
C++11 提供的 <future> 头文件中包含了以下几个类和函数:
- Providers 类:
std::promise
,std::package_task
; - Futures 类:
std::future
,shared_future
; - Providers 函数:
std::async()
; - 其他类型:
std::future_error
,std::future_errc
,std::future_status
,std::launch
;
std::future构造函数
std::future
一般由上面三种 Provider 创建,不过也提供了构造函数:
// default 由 std::future 默认构造函数创建的 future 对象不是有效的
future() noexcept;
// copy [deleted]
future (const future&) = delete;
// move
future (future&& x) noexcept;
不过std::future
的拷贝构造函数是被禁用的,只提供了默认的构造函数和 move 构造函数。另外,std::future
的普通赋值操作也被禁用,只提供了 move 赋值操作。如下代码所示:
std::future<int> fut; // 默认构造函数
fut = std::async(do_some_task); // move-赋值操作。
future
作为线程间一种同步手段,还有一个知识就是其共享状态。所谓共享状态就是这个 future
对象所表示的异步操作是否能够在其他线程中被访问。一般来说,通过异步操作创建的 future
会被这些异步操作设置共享状态 。future
对象可以通过 valid()
函数查询其共享状态是否有效 ,一般来说,只有当 valid()
返回 true
的时候才调用 get()
去获取结果,
std::future::share()
返回一个 std::shared_future
对象,调用该函数之后,该 std::future 对象本身已经不和任何共享状态相关联,因此该 std::future 的状态不再是 valid 的了。
std::shared_future<T> share() noexcept;
#include <iostream> // std::cout
#include <future> // std::async, std::future, std::shared_future
int do_get_value() { return 10; }
int main ()
{
std::future<int> fut = std::async(do_get_value);
std::shared_future<int> shared_fut = fut.share();
// 共享的 future 对象可以被多次访问.
std::cout << "value: " << shared_fut.get() << '\n';
std::cout << "its double: " << shared_fut.get()*2 << '\n';
return 0;
}
std::future::get()
std::future::get 一共有三种形式:
T get(); // (仅为泛型 future 模板的成员)
T& get(); // (仅为 future<T&> 模板特化的成员)
void get(); // (仅为 future<void> 模板特化的成员)
当与该 std::future 对象相关联的共享状态标志变为 ready 后,调用该函数将返回保存在共享状态中的值,如果共享状态的标志不为 ready,则调用该函数会阻塞当前的调用者,而此后一旦共享状态的标志变为 ready,get 返回 Provider 所设置的共享状态的值或者异常(如果抛出了异常)。
std::future::valid()
bool valid() const noexcept;
检查当前的 std::future 对象是否有效,即释放与某个共享状态相关联。一个有效的 std::future 对象只能通过 std::async(), std::future::get_future 或者 std::packaged_task::get_future 来初始化。另外由 std::future 默认构造函数创建的 std::future 对象是无效(invalid)的,当然通过 std::future 的 move 赋值后该 std::future 对象也可以变为 valid。
std::future::wait()
等待与当前std::future 对象相关联的共享状态的标志变为 ready。
如果共享状态的标志不是 ready,调用该函数会被阻塞当前线程,直到共享状态的标志变为 ready。一旦共享状态的标志变为 ready,wait() 函数返回,当前线程被解除阻塞,但是 wait() 并不读取共享状态的值或者异常。
std::future::wait_for()
与 std::future::wait() 的功能类似,即等待与该 std::future 对象相关联的共享状态的标志变为 ready,该函数原型如下:
template< class Rep, class Period >
std::future_status wait_for( const std::chrono::duration<Rep,Period>& timeout_duration ) const;
而与 std::future::wait() 不同的是,wait_for() 可以设置一个时间段 rel_time,如果共享状态的标志在该时间段结束之前没有被 Provider 设置为 ready,则调用 wait_for 的线程被阻塞,在等待了 timeout_duration 的时间长度后 wait_until() 返回,返回值如下:
future status::ready | 共享状态的标志已经变为 ready,即 Provider 在共享状态上设置了值或者异常。 |
future status::timeout | 超时,即在规定的时间内共享状态的标志没有变为 ready。 |
future status::deferred | 共享状态包含一个 deferred 函数。 |
std::future::wait_until()
与 std::future::wait() 的功能类似,即等待与该 std::future 对象相关联的共享状态的标志变为 ready,该函数原型如下:
template< class Clock, class Duration >
std::future_status wait_until( const std::chrono::time_point<Clock,Duration>& timeout_time ) const;
而 与 std::future::wait() 不同的是,wait_until() 可以设置一个系统绝对时间点 abs_time,如果共享状态的标志在该时间点到来之前没有被 Provider 设置为 ready,则调用 wait_until 的线程被阻塞,在 abs_time 这一时刻到来之后 wait_for() 返回,返回值如下:
future status::ready | 共享状态的标志已经变为 ready,即 Provider 在共享状态上设置了值或者异常。 |
future status::timeout | 超时,即在规定的时间内共享状态的标志没有变为 ready。 |
future status::deferred | 共享状态包含一个 deferred 函数。 |
std::shared_future
std::shared_future 共有四种构造函数,如下所示:
shared_future() noexcept; // default
shared_future (const shared_future& x); // copy
shared_future (shared_future&& x) noexcept; // move
shared_future (future<T>&& x) noexcept; // move from future
std::shared_future 与 std::future 类似,但是 std::shared_future 可以拷贝、多个 std::shared_future 可以共享某个共享状态的最终结果(即共享状态的某个值或者异常)。shared_future 可以通过某个 std::future 对象隐式转换,或者通过 std::future::share() 显示转换,无论哪种转换,被转换的那个 std::future 对象都会变为 not-valid。
标签:std,get,future,shared,共享,wait From: https://www.cnblogs.com/love-9/p/18095047