- 头文件<future>
- async函数
- future类
- 构造函数
- 成员函数
- 示例代码
- shared_future类
- 构造函数
- 成员函数
- 示例代码
- promise类
- 构造函数
- 成员函数
- 示例代码
- packaged_task类
- 构造函数
- 成员函数
- 重载的运算符
- 示例代码
- Shared State
头文件
包含标准标头<future>,以定义类模板和支持模板,它们可简化(可能在单独线程中的)函数运行并检索其结果。 结果可以是由函数返回的值或由函数发出但函数中未捕获的异常。
async函数
(1)带launch策略的
template <class Fn, class... ArgTypes>
future<typename result_of<Fn(ArgTypes...)>::type> async(launch policy, Fn&& fn, ArgTypes&&... args);policy:launch策略
fn:要异步执行的函数或可调用对象
args:函数形参,尽量以值传递的方式进行传递,async只需使用局部拷贝,如果复制成本太大,考虑使用const reference形式传递,且不使用mutable。无形参不需要传递
【返回值】:返回一个std::future对象,通过该对象可以获取异步操作的结果或等待其完成。
launch策略:
- std::launch::async 尝试以异步方式启动目标函数,不推延目标函数的执行,如果办不到,抛出std::system_error异常
- std::launch::deferred 强制延缓目标函数的执行,直到future对象调用get方法为止
- std::launch::async | std::launch::deferred 系统根据当前形势选择最合适的方式(默认行为)
(2)不带launch策略的(相当于上面构造函数launch策略为std::launch::async | std::launch::deferred)
template <class Fn, class... ArgTypes>
future<typename result_of<Fn(ArgTypes...)>::type> async(Fn&& fn, ArgTypes&&... args);
future类
描述异步返回对象
template <class Ty>
class future;// Disable copying
future(const future&) = delete;
future& operator=(const future&) = delete;
future类禁用了拷贝构造和赋值运算符,因此future对象本身是不可复制的,如果它用作函数形参,应设置为引用类型。
构造函数
(1)构造没有关联异步状态的 future 对象
future() noexcept;
(2)构造 future 对象并从 Other 传输关联异步状态。 Other 不再具有关联异步状态。
future(future&& Other) noexcept; // 移动构造Other:future 对象,该形式通常结合async函数使用。
成员函数
(1)get
获取异步操作的结果。
Ty future<Ty>::get()
Ty& future<Ty&>::get()
void future<void>::get()
- 在检索结果前,该方法会阻止当前线程,直到关联异步状态为准备就绪。
- 对于部分专用化 future<Ty&> ,存储值实际上是对已传递给异步提供程序作为返回值的对象的引用。
- 专用化 future<void> 不存在任何存储值,所以此方法会返回 void 。
- 在其他专用化中,此方法会从存储值移动其返回值。 因此请仅调用此方法一次。
- 如果异步操作抛出异常,get()会重新抛出异常。
- get会令future处于无效状态,面对无效的future,调用其析构函数、move assignment操作符火valid()以外的任何操作,都会导致不可预期的行为,通常会抛出一个差错码:std::future_error: No associated state
(2)share
将对象转换为 shared_future 对象。
shared_future<Ty> share();返回值为shared_future(move(*this))
(3)wait
阻塞当前线程,直到异步操作完成(即结果已经准备好)。
强制启动该future对象象征的线程并等待这一后台操作终止。
void wait() const;
只有当其异步提供程序存储了返回值或存储了异常时,关联的异步状态才会为准备就绪。
(4)wait_for
阻塞当前线程一段指定的时间,直到异步操作完成或超时。
用于等待一个异步操作在指定的时间段内完成,如果传入zero时间段,就表示轮询是否有个后台任务被启动。
template <class Rep, class Period>
future_status wait_for(const chrono::duration<Rep, Period>& Rel_time) const;Rel_time:一个 chrono::duration 对象,指定线程阻止的最大时间间隔,如果传入0或者一个负数,就能够仅轮询是否有个后台任务已被启动。
返回值:一个 future_status,指示返回的原因。
- 只有当其异步提供程序存储了返回值或存储了异常时,关联的异步状态才会为准备就绪。
- 如果异步操作在指定的时间内完成,则返回std:future_status::ready;否则返回std:future_status::timeout;
- 注意:如果async()延缓了操作而程序中又完全没又调用wait()或get(),那么函数wait_for、wait_until会立刻返回。
关于future_status枚举类,定义如下
enum future_status{ready,timeout,deferred
};ready:异步操作已完成,并且结果已经准备好可以获取
timeout:等待超时,异步操作还未完成
deferred:异步操作被延迟执行,即任务尚未开始
(5)wait_until
阻止当前线程,直到关联的异步状态为准备就绪或直到指定时间点后。
如果传入一个过去时间点,就表示轮询是否有个后台任务被启动。
template <class Clock, class Duration>
future_status wait_until(const chrono::time_point<Clock, Duration>& Abs_time) const;Abs_time:time_point对象,表示一个绝对时间点。
返回值:一个 future_status,指示返回的原因。
(6)valid()
检查future对象是否具有关联异步状态。
bool valid() noexcept;
(7)operator=
从指定对象传输关联异步状态。
future& operator=(future&& Right) noexcept;
示例代码
(1)示例代码1:测试async函数和future对象的配合使用,并借助future对象获取函数的结果
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <random>
#include <exception>using namespace std;//
int doSomething(char c)
{default_random_engine dre(c);uniform_int_distribution<int> id(10, 1000);for (int i = 0; i < 10; ++i){// 当前线程休眠10~1000毫秒this_thread::sleep_for(chrono::milliseconds(id(dre)));cout.put(c).flush();}return c;
}int func1()
{return doSomething('.');
}int func2()
{return doSomething('+');
}int main()
{std::cout << "在后台启动func1函数,在主线程启动func2函数:\n";//future<int> func1_future = async(func1);// 包含了默认的发射策略std::launch::async | std::launch::deferred//future<int> func1_future1(async(func1));// 指定发射策略尝试以异步方式启动目标函数future<int> func1_future1(async(std::launch::async, func1));// 指定为延缓策略,强制延缓目标函数的执行//future<int> func1_future1(async(std::launch::deferred, func1));int res2 = func2();// 获取func1的结果// 默认策略和异步方式下打印字符为:++..++++.++.+.+.....// 在推迟策略下打印为:++++++++++..........//int res = func1_future1.get() + res2;int res = res2 + func1_future1.get() ;cout << "\nfunc1 + func2的结果为:" << res << endl;
}
运行结果:
在后台启动func1函数,在主线程启动func2函数:
++..++++.++.+.+.....
func1 + func2的结果为:89
(2)示例代码2:主要测试future对象调用get方法时处理异常的方式
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <random>
#include <exception>
#include <stdexcept>
#include <list>using namespace std;void task1()
{cout << "task1执行中..." << endl;throw "exception!";
}void task2()
{cout << "task2执行中..." << endl;
}int main()
{auto f1 = async(std::launch::deferred,task1);auto f2 = async(task2);try {f1.get();f2.get();}catch (const char* msg) {cerr << "\n发生异常:" << msg << endl;}}
运行结果:
task1执行中...
task2执行中...发生异常:exception!
(3) future对象调用wait_for方法
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <random>
#include <exception>using namespace std;int doSomething(char c)
{default_random_engine dre(c);uniform_int_distribution<int> id(10, 100);for (int i = 0; i < 2; ++i){// 当前线程休眠10~100毫秒this_thread::sleep_for(chrono::milliseconds(id(dre)));cout.put(c).flush();}cout << "\n打印字符" << c << "完毕" << endl;return c;
}void print_future_state(future_status status,const char* str){switch (status) {case future_status::ready:cout << " task is ready " << str << endl;break;case future_status::timeout:cout << " task is timeout " << str << endl;break;case future_status::deferred:cout << " task is deferred " << str << endl;break;}
}int main()
{cout << "启动两个异步任务..." << endl;auto f1 = async([] {doSomething('.'); });auto f2 = async([] {doSomething('+'); });print_future_state(f1.wait_for(chrono::seconds(0)), "f1_1");print_future_state(f2.wait_for(chrono::seconds(0)), "f2_1");// 确保两个线程至少有一个启动了,初始时,f1和f2均处于future_status::timeoutif (f1.wait_for(chrono::seconds(0)) != future_status::deferred ||f2.wait_for(chrono::seconds(0)) != future_status::deferred) {// 如果两个线程任务均为未准备就绪状态,则建议操作系统将当前线程挂起print_future_state(f1.wait_for(chrono::seconds(0)), "f1_2");print_future_state(f2.wait_for(chrono::seconds(0)), "f2_2");while (f1.wait_for(chrono::seconds(0)) != future_status::ready &&f2.wait_for(chrono::seconds(0)) != future_status::ready){this_thread::yield();print_future_state(f1.wait_for(chrono::seconds(0)), "f1_3");print_future_state(f2.wait_for(chrono::seconds(0)), "f2_3");}print_future_state(f1.wait_for(chrono::seconds(0)), "f1_4");print_future_state(f2.wait_for(chrono::seconds(0)), "f2_4");}cout.put('\n').flush();print_future_state(f1.wait_for(chrono::seconds(0)), "f1_5");print_future_state(f2.wait_for(chrono::seconds(0)), "f2_5");try {f1.get();f2.get();}catch (const exception& e) {cerr << "发生异常:" << e.what() << endl;}cout << "\n任务完成..." << endl;
}
运行结果:在f1_3和f2_3处有多组重复,人工做了删减
启动两个异步任务...task is timeout f1_1task is timeout f2_1task is timeout f1_2task is timeout f2_2task is timeout f1_3task is timeout f2_3重复打印(f1_3,f2_3)task is timeout f1_3task is timeout f2_3task is timeout f1_3task is timeout f2_3
+. task is timeout f1_3task is timeout f2_3重复打印(f1_3,f2_3)task is timeout f1_3task is timeout f2_3
.
打印字符.完毕task is timeout f1_3task is timeout f2_3task is ready f1_4task is timeout f2_4task is ready f1_5task is timeout f2_5task is timeout f2_6
+
打印字符+完毕任务完成...
(4)使用async函数,并传递参数
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <random>
#include <exception>using namespace std;int doSomething(char c)
{default_random_engine dre(c);uniform_int_distribution<int> id(10, 100);for (int i = 0; i < 2; ++i){cout.put(c).flush();}
// cout << "\n打印字符" << c << "完毕" << endl;return c;
}class CC{
public:void mem(int num){cout << "CC num = " << num << endl;}
};class DD{
public:void operator()(int num){cout << "DD num = " << num << endl;}};int main()
{char ch = '+';const char & ch1 = '-';char ch3 = '*';const char & ch4 = '/';// lambda表达式,值传递auto f1 = async(std::launch::async,[=](){doSomething(ch);});// lambda表达式,引用传递auto f2 = async(std::launch::async,[&](){doSomething(ch1);});// 直接传递函数入口地址auto f3 = async(std::launch::async,doSomething, ch3); // 值传递auto f4 = async(std::launch::async,doSomething, ch4); // 引用传递// 类的成员函数CC cc;auto f5 = async(std::launch::deferred, &CC::mem, cc, 5);auto f5_1 = async(std::launch::deferred, [&cc]{cc.mem(50);});f5.get();f5_1.wait(); // 强制启动任务并等待这一后台操作终止// 仿函数DD dd;auto f6 = async(std::launch::deferred, dd, 6);f6.get();// 函数指针int (*ds_ptr)(char);ds_ptr = doSomething;auto f7 = async(std::launch::deferred, ds_ptr, '@');f7.get();
}
可能出现的运行结果:
CC num = ++5
CC num = 50
DD num = 6
@**--//@
shared_future类
future类的子类,描述异步返回对象。 相较于 future 对象,异步提供程序可与任意数量的 shared_future对象关联。
template <class Ty>
class shared_future;shared_future(const shared_future& __sf) : _Base_type(__sf) { }
shared_future& operator=(const shared_future& __sf)
与父类不同的是,shared_future支持拷贝构造和赋值运算符。
构造函数
(1)构造没有关联异步状态的 shared_future 对象。
shared_future() noexcept; // 默认构造
(2)构造 shared_future 对象并从 Right 传输关联异步状态
shared_future(future<Ty>&& Right) noexcept; // 移动构造
shared_future(shared_future&& Right) noexcept;Right:一个 future 或 一个 shared_future 对象。Right不再具有关联异步状态。
(3)构造与 shared_future 对象具有相同关联异步状态的 Right 对象。
shared_future(const shared_future& Right); // 拷贝构造
成员函数
成员函数与父类future类似,只是在get方法中略有区别
名称 | 描述 |
---|---|
get | 检索存储在关联异步状态中的结果。 |
valid | 指定对象是否不为空 |
wait | 阻止当前线程,直到关联异步状态为准备就绪 |
wait_for | 进行阻止,直到关联异步状态为准备就绪或已过指定时间段 |
wait_until | 进行阻止,直到关联异步状态为准备就绪或直到指定时间点 |
(1)get方法
const Ty& shared_future<Ty>::get() const; // future类返回为Ty
Ty& shared_future<Ty&>::get() const; // 这种做法风险较高,因为必须确保share_future对象的寿命,否则容易导致不可预知的行为
void shared_future<void>::get() const; // 同future
- 允许多次调用get(),get方法不令其状态失效
- 如果结果为异常,该方法将重新引发它。 否则,会返回结果。
- 在检索结果前,该方法会阻止当前线程,直到关联异步状态为准备就绪。
- 对于部分专用化 shared_future<Ty&> ,存储值实际上是对已传递给异步提供程序作为返回值的对象的引用。
- 因为专用化 shared_future<void> 不存在任何存储值,所以此方法会返回 void 。
(2)重载运算符=
// 对于第一个运算符,操作后 Right 不再具有关联异步状态。
shared_future& operator=(shared_future&& Right) noexcept;// 对于第二个方法,Right 保留其关联异步状态,支持拷贝复制(copy assignment)操作符
shared_future& operator=(const shared_future& Right);
示例代码
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <random>
#include <exception>using namespace std;void doSomething(char c, shared_future<int>& f)
{try {int num = f.get();for(int i = 0; i < num; i++){this_thread::sleep_for(chrono::milliseconds(100));cout.put(c).flush();}} catch (const exception& e) {cerr << "线程" << this_thread::get_id() << " 发生异常:" << e.what() << endl;}
}int queryNumber(){cout << "read number: ";int num;cin >> num;if(!cin){throw runtime_error("no number read");}return num;
}int main(){try {shared_future<int> sf = async(queryNumber);// 传递引用,它们共享同一个shared_future对象,由该对象在doSomething里面调用多次get方法// 但传递引用的做法风险较高,实际还是推荐按值传递auto f1 = async(std::launch::async, doSomething, '+', ref(sf));auto f2 = async(std::launch::async, doSomething, '-', ref(sf));auto f3 = async(std::launch::async, doSomething, '*', ref(sf));auto f4 = async(std::launch::async, doSomething, '/', ref(sf));f1.get();f2.get();f3.get();f4.get();} catch (const exception& e) {cout << "\n 主函数捕获到异常:" << e.what() << endl;}cout << "\ndone" << endl;
}
运行结果:
read number: 6
+-/*+-*/-*+/*-/++-/*+-/*
done
promise类
promise类用于线程间通信的一种机制,它允许一个线程(生产者)将值或异常传递给另一个线程(消费者)。
promise& operator=(const promise&) = delete;
promise(const promise&) = delete;
promise类禁用了拷贝构造和赋值运算符,因此promise对象本身是不可复制的。当传递promise对象的引用时,多个线程可以共享同一个promise对象。这允许一个线程设置promise对象的值,而另一个线程等待并获取这个值。
构造函数
(1)默认构造
promise();
没有关联的共享状态,需要手动与std::future关联使用。
(2)使用指定的内存分配器
template <class Alloc>
promise(allocator_arg_t, const Alloc& Al);Al:内存分配器,使用它实现内存分配
(3)移动构造
promise(promise&& Other) noexcept;
成员函数
函数名 | 描述 |
---|---|
get_future | 返回与此 promise 关联的 future。 |
set_exception | 以原子方式设置此 promise 的结果以指示异常。 |
set_exception_at_thread_exit | 以原子方式设置此 promise 的结果以指示异常,并且仅在销毁当前线程中的所有线程本地对象后(通常在线程退出时)发出通知。 |
set_value | 以原子方式设置此 promise 的结果以指示值。 |
set_value_at_thread_exit | 以原子方式设置此 promise 的结果以指示值,并且仅在销毁当前线程中的所有线程本地对象后(通常在线程退出时)发出通知。 |
swap | 用指定的 promise 对象的关联的异步状态交换此 promise 的关联的异步状态。 |
= | 转移关联状态 |
(1)get_future
返回与当前promise对象关联的future对象,该future对象可用于获取promise设置的值或异常。
std::future<T> get_future
(2)set_exception
设置promise对象的异常,并将“关联的异步状态”设置为“就绪”。
void set_exception(exception_ptr __p)__p:一个指向异常对象的指针。
- 如果 promise 对象没有关联的异步状态,则此方法将引发具有错误代码 no_state 的future_error。
- 如果已为具有相同的关联异步状态的 promise 对象调用 set_exception 、set_exception_at_thread_exit、set_value 或 set_value_at_thread_exit,则此方法将引发具有错误代码 promise_already_satisfied 的 future_error 。
(3)set_exception_at_thread_exit
设置promise对象的异常,并且能在销毁当前线程中的所有线程本地对象后(通常在线程退出时)发出通知。
void set_exception_at_thread_exit(exception_ptr __p)
与 set_exception 相反,此方法在当前线程中的所有线程本地对象被销毁前不会将关联的异步状态设置为“就绪”。 通常,在关联的异步状态上受阻的线程直到当前线程退出才会取消阻止。
(4)set_value
设置promise对象的值,并将“关联的异步状态”设置为“就绪”。
void promise::set_value(const T& __r)void promise::set_value(T&& __r) // 移动语义版本void promise<Ty&>::set_value(T& Val);void promise<void>::set_value(); // 特化版本,void__r:要设置的值
(5)set_value_at_thread_exit
设置promise对象的值,并且能在销毁当前线程中的所有线程本地对象后(通常在线程退出时)发出通知。
void promise::set_value_at_thread_exit(const T& __r) void promise::set_value_at_thread_exit(T&& __r) // 移动语义版本void promise<Ty&>::set_value_at_thread_exit(T& Val);void promise<void>::set_value_at_thread_exit(); // 特化版本,void
(6)swap
交换两个promise对象的内容
void swap(promise& other) noexcept
(7)=
promise& operator=(promise&& Other) noexcept;
示例代码
#include <iostream>
#include <future>
#include <random>
#include <thread>using namespace std;void producer(std::promise<int>& prom)
{auto now = chrono::system_clock::now();std::time_t now_tm_t = chrono::system_clock::to_time_t(now);std::tm* now_tm = localtime(&now_tm_t);int hour = now_tm->tm_hour;int minute = now_tm->tm_min;int sec = now_tm->tm_sec;int seed = hour * 3600 + minute * 60 + sec;this_thread::sleep_for(chrono::seconds(1));std::default_random_engine dre(seed);std::uniform_int_distribution<int> uid(0, 100);try {int res = uid(dre);cout << "producer produce value: " << res << endl;prom.set_value(res);} catch (...) {prom.set_exception(std::current_exception());}
}void consumer(future<int>& fut)
{try {int value = fut.get();if(value <= 50){throw std::runtime_error("number " + to_string(value) + " produce exception");}cout << "consumer get value: " << value << endl;}catch(const exception& e){cerr << "consumer exception: " << e.what() << endl;}catch (...) {cerr << "consumer exception: " << endl;}
}int main(){promise<int> p;future<int> fut = p.get_future();try {thread produceThread(producer, ref(p));thread consumeThread(consumer, ref(fut));produceThread.join();consumeThread.join();
// cout << "result: " << fut.get() << endl;} catch (const exception& e) {cerr << "\ncatch exception: " << e.what() << endl;}catch(...){cerr << "exception: " << endl;}cout << "\ndone" << endl;
}
运行结果:
产生异常运行结果:
consumer exception: number 0 produce exceptiondone正常运行产生结果:
producer produce value: 60
consumer get value: 60done
packaged_task类
package_task类用于包装一个可调用对象,使其能够与std::future协同工作,实现异步任务执行和结果传递。
template<typename _Res, typename... _ArgTypes>
class packaged_task<_Res(_ArgTypes...)>// No copy
packaged_task(const packaged_task&) = delete;
packaged_task& operator=(const packaged_task&) = delete;
不支持拷贝构造和赋值运算符,因此package_task对象也是不可复制的。
构造函数
(1)默认构造
packaged_task() noexcept;
构造没有关联异步状态的 packaged_task 对象
(2)移动构造
packaged_task(packaged_task&& Right) noexcept;
构造 packaged_task 对象并从 Right 传输关联异步状态。 操作后,Right不再具有关联异步状态。
(3)初始化构造
template <class Fn>
explicit packaged_task(Fn&& fn);fn:可调用对象,如函数指针、仿函数、lambda表达式等
构造 packaged_task 对象,该对象具有存储在其关联异步状态中的 fn 的副本。
(4)带自定义内存分配器的构造
template <class Fn, class Alloc>
explicit packaged_task(allocator_arg_t, const Alloc& alloc, Fn&& fn);alloc:内存分配器,使用它实现内存分配
fn:可调用对象,如函数指针、仿函数、lambda表达式等
成员函数
名称 | 描述 |
---|---|
get_future | 返回具有相同关联异步状态的 future 对象。 |
make_ready_at_thread_exit | 调用存储在关联异步状态中的可调用的对象,并以原子方式存储返回值。 |
reset | 替换关联异步状态。 |
swap | 将关联异步状态与指定对象交换。 |
valid | 指定对象是否具有关联异步状态。 |
(1)get_future
返回一个与package_task对象的共享状态关联的std::future对象。
future<T> get_future();
- 如果 packaged_task 对象没有关联的异步状态,则此方法将引发具有错误代码 no_state的 future_error。
- 如果已为具有相同关联异步状态的 packaged_task 对象调用此方法,则此方法将引发具有错误代码 future_already_retrieved 的 future_error 。
(2)make_ready_at_thread_exit
调用task并在线程退出时才使共享状态ready,而不是在调用完成后就立即ready。
void make_ready_at_thread_exit(ArgTypes... args);args:task所需的实参
用来确保在task的成果被处理之前,终结该task的线程的局部对象和其它材料会先被妥善清理。
(3)reset
使用新的关联异步状态替换现有的关联异步状态。
void reset()
实际上,此方法将执行 *this = packaged_task(move(fn)) ,其中 fn 是存储在此对象的关联异步状态中的函数对象。 因此,将清除该对象的状态,且可像在新构造的对象上一样调用 get_future、operator() 和 make_ready_at_thread_exit。
(4)swap
将关联异步状态与指定对象交换。
void swap(packaged_task& Right) noexcept;Right:要交换的另一个packaged_task对象
(5)valid
检查当前对象是否具有共享异步状态
bool valid() const;
重载的运算符
(1)=
packaged_task& operator=(packaged_task&& Right); // 移动语义
(2)()
调用存储在关联异步状态中的可调用的对象,以原子方式存储返回值,并将其状态设置为就绪。
void operator()(ArgTypes... args);args:可调用对象需要的实参
(3)bool
检查当前对象是否具有共享异步状态
operator bool() const noexcept;
示例代码
(1)示例代码1
#include <iostream>
#include <future>
#include <random>
#include <thread>using namespace std;int doSomething(char c)
{default_random_engine dre(c);uniform_int_distribution<int> id(10, 1000);for (int i = 0; i < 10; ++i){// 当前线程休眠10~1000毫秒this_thread::sleep_for(chrono::milliseconds(id(dre)));cout.put(c).flush();}return c;
}int main(){packaged_task<int(char)> pt(doSomething);future<int> ft = pt.get_future();auto f1 = async(std::launch::async, doSomething, '+');cout << "f1 res:" << f1.get() << endl;thread t1(doSomething, '-');t1.join();cout << '\n';// 用packaged_task对象启动任务pt('*');int res = ft.get();cout << "\nres = " << res << endl;
}
运行结果:
f1 res:++++++++++43
----------
**********
res = 42
(2)示例代码2
#include <iostream>
#include <future>
#include <thread>using namespace std;int main(){std::packaged_task<int(int,int)> task([](int a, int b){return a+b;});try {auto fut = task.get_future();// std::thread t1(task, 3, 4); 错误,packaged_task对象不支持拷贝构造std::thread t(std::move(task), 3, 4);t.join();cout << "res = " << fut.get() << endl;} catch (const exception& e) {cout << "exception:" << e.what() << endl;}}
运行结果:
res = 7
Shared State
share state是反复提到的一个中心概念,它允许“启动及控制后台机能”的对象
(如promise,packaged_task,async函数)能够和“处理其结果”的对象(future,shared_future)相互沟通
。它能够保存计算结果和相关状态信息。该对象通常由async、promise和package_task等提供,并由future/shared_future管理,作为异步结果的传输通道,允许多个线程访问同一结果。