C++11中的std::shared_future是个模板类。与std::future类似,std::shared_future提供了一种访问异步操作结果的机制;不同于std::future,std::shared_future允许多个线程等待同一个共享状态;不同于std::future仅支持移动操作,std::shared_future既支持移动操作也支持拷贝操作,而且多个shared_future对象可以引用相同的共享状态。std::shared_future还允许一旦共享状态就绪就可以多次检索共享状态下的值(A shared_future object behaves like a future object, except that it can be copied, and that more than one shared_future can share ownership over their end of a shared state. They also allow the value in the shared state to be retrieved multiple times once ready)。
std::shared_future对象可以通过std::future对象隐式转换,也可以通过显示调用std::future::share显示转换,在这两种情况下,原std::future对象都将变得无效。
共享状态(shared state)的生存期至少要持续到与之关联的最后一个对象被销毁为止。与std::future不同,通过shared_future::get检索的值不会释放共享对象的所有权。
std::future介绍参考:https://blog.csdn.net/fengbingchun/article/details/104115489
当你需要具有std::future的多个有效拷贝时会用到std::shared_future;或者多个使用者使用std::future时也会用到std::shared_future。
Consider std::future, std::shared_future to be like std::unique_ptr, std::shared_ptr.
模板类std::shared_future成员函数包括:
1. 构造函数:(1).不带参数的默认构造函数,此对象没有共享状态,因此它是无效的,但是它可以被赋予一个有效值;(2).拷贝构造:与const shared_future& x具有相同的共享状态,并与之共享所有权;(3).支持移动构造。
2. 析构函数:销毁shared_future对象,它是异常安全的。如果对象有效(即它可以访问共享状态),则将其与对象接触关联;如果它是与共享状态关联的唯一对象,则共享对象本身也将被销毁。
3. get函数:(1).当共享状态就绪时,返回存储在共享状态中的值的引用(或抛出异常)。(2).如果共享状态尚未就绪(即provider提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将解除阻塞并返回(或抛出),但与future::get不同,不会释放其共享状态,允许其它shared_future对象也访问存储的值。(4).std::shared_future<void>::get()不返回任何值,但仍等待共享状态就绪才返回或抛出。
4. operator=:(1).拷贝赋值:该对象与const shared_future& rhs关联到相同的共享状态,并与之共享所有权;(2).移动赋值:该对象获取shared_future&& rhs的共享状态,rhs不再有效。
5. valid函数:检查共享状态的有效性,返回当前的shared_future对象是否与共享状态关联。
6. wait函数:(1).等待共享状态就绪。(2).如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将解除阻塞并void返回。
7. wait_for函数:(1).等待共享状态在指定的时间内(time span)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到设置的时间。(3).此函数的返回值类型为枚举类future_status。此枚举类有三种label:ready:共享状态已就绪;timeout:在指定的时间内未就绪;deferred:共享状态包含了一个延迟函数(deferred function)。(4).如果共享状态包含了一个延迟函数,则该函数不会阻塞,立即返回一个future_status::deferred值。
8. wait_until函数:(1). 等待共享状态在指定的时间点(time point)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到指定的时间点。(3).此函数的返回值类型为枚举类future_status。(4).如果共享状态包含了一个延迟函数,则该函数不会阻塞,立即返回一个future_status::deferred值。
详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:
-
#include "future.hpp"
-
#include <iostream>
-
#include <future>
-
#include <chrono>
-
#include <utility>
-
#include <thread>
-
-
namespace future_ {
-
-
///////////////////////////////////////////////////////////
-
// reference: https://en.cppreference.com/w/cpp/thread/shared_future
-
int test_shared_future_1()
-
{
-
std::promise<
void> ready_promise, t1_ready_promise, t2_ready_promise;
-
// 通过std::future移动构造std::shared_future对象,t1_ready_promise和t2_ready_promise均会用到ready_future
-
std::shared_future<
void> ready_future(ready_promise.get_future());
-
-
std::chrono::time_point<
std::chrono::high_resolution_clock> start;
-
-
auto fun1 = [&, ready_future]() ->
std::chrono::duration<
double,
std::milli> {
-
t1_ready_promise.set_value();
-
ready_future.wait();
// waits for the signal from main()
-
return
std::chrono::high_resolution_clock::now() - start;
-
};
-
-
auto fun2 = [&, ready_future]() ->
std::chrono::duration<
double,
std::milli> {
-
t2_ready_promise.set_value();
-
ready_future.wait();
// waits for the signal from main()
-
return
std::chrono::high_resolution_clock::now() - start;
-
};
-
-
auto fut1 = t1_ready_promise.get_future();
-
auto fut2 = t2_ready_promise.get_future();
-
-
auto result1 =
std::async(
std::launch::async, fun1);
-
auto result2 =
std::async(
std::launch::async, fun2);
-
-
// wait for the threads to become ready
-
fut1.wait();
-
fut2.wait();
-
-
// the threads are ready, start the clock
-
start =
std::chrono::high_resolution_clock::now();
-
-
// signal the threads to go
-
ready_promise.set_value();
-
-
std::
cout <<
"Thread 1 received the signal " << result1.get().count() <<
" ms after start\n"
-
<<
"Thread 2 received the signal " << result2.get().count() <<
" ms after start\n";
-
-
return
0;
-
}
-
-
///////////////////////////////////////////////////////////
-
// reference: https://en.cppreference.com/w/cpp/thread/shared_future/wait
-
int fib(int n)
-
{
-
if (n <
3)
return
1;
-
else
return fib(n -
1) + fib(n -
2);
-
}
-
-
int test_shared_future_2()
-
{
-
// 将std::shared_future<int>调整为std::future<int>也是正确的
-
std::shared_future<
int> f1 =
std::async(
std::launch::async, []() {
return fib(
20); });
-
std::shared_future<
int> f2 =
std::async(
std::launch::async, []() {
return fib(
25); });
-
-
std::
cout <<
"waiting...\n";
-
f1.wait();
-
f2.wait();
-
-
std::
cout <<
"f1: " << f1.get() <<
'\n';
-
std::
cout <<
"f2: " << f2.get() <<
'\n';
-
-
return
0;
-
}
-
-
///////////////////////////////////////////////////////////
-
// reference: https://en.cppreference.com/w/cpp/thread/shared_future/wait_for
-
int test_shared_future_3()
-
{
-
// 将std::shared_future<int>调整为std::future<int>也是正确的
-
std::shared_future<
int> future =
std::async(
std::launch::async, [](){
-
std::this_thread::sleep_for(
std::chrono::seconds(
3));
-
return
8;
-
});
-
-
std::
cout <<
"waiting...\n";
-
std::future_status status;
-
do {
-
status = future.wait_for(
std::chrono::seconds(
1));
-
if (status ==
std::future_status::deferred) {
-
std::
cout <<
"deferred\n";
-
}
else
if (status ==
std::future_status::timeout) {
-
std::
cout <<
"timeout\n";
-
}
else
if (status ==
std::future_status::ready) {
-
std::
cout <<
"ready!\n";
-
}
-
}
while (status !=
std::future_status::ready);
-
-
std::
cout <<
"result is " << future.get() <<
'\n';
-
-
return
0;
-
}
-
-
}
// namespace future_
GitHub:https://github.com/fengbingchun/Messy_Test
转载:https://blog.csdn.net/fengbingchun/article/details/104118831