**
前言
**
前面所写的多线程处理的代码中,线程入口函数都是无返回值的,并且在传递参数时特别麻烦。
现在有了另外的解决方案,使用future期望,为了处理线程间的变量的传递,其设定了共享状态标志future_status。
等待一次事件
你等了一辆出租车后就坐车走了,不需要再等第二辆,也就是说只要有一辆过来就行,这就叫等待一次事件。
在期望中,变量最多只能set一次和get一次。
如何拥有共享状态?< future >头文件里有啥?
Providers类:promise,packaged_task
Futures类:future,shared_future
Providers函数: async()
其他类型:future_error,future_errc,future_status,launch
promise类
promise对象可以保存某一类型T的值,该值可被future对象读取(可能在另外一个线程中),因此 promise 也提供了 一种线程同步的手段。
在 promise 对象构造时可以和一个共享状态(通常)相关联,并可以在相关联的共享状态上保存一个类型为T的值。
可以通过get_future来获取与该promise 对象相关联的 future对象,调用该函数后,两个对象共享状态同步
promise对象是异步Provider,可以在某一时刻设置共享状态的值
future对象可以异步返回共享状态的值,或者在必要的情况下阻塞调用者并等待共享状态标志变为ready,然后才能获取共享状态的值
void test01(){
promise<int> p; //生成一个promise对象
future<int> f = p.get_future();//和future关联
auto lam = [](future<int>& f) {
int x = f.get();//获取共享状态的值
cout << "value = " << x << "\n";
};
thread t( lam, std::ref(f));
p.set_value(10);//设置共享状态的值,此处和线程 t 保持同步
t.join();
}
如果是把promise对象赋值给一个新的promise对象,线程入口函数就不能有参数
promise<int> p;
void test02() {
auto lam = []() {
future<int> f = p.get_future();
int x = f.get();
cout << "value = " << x << endl;
};
thread t1(lam);
p.set_value(10);
t1.join();
p = promise<int>(); //p被move赋值给一个新的promise对象
thread t2(lam);
p.set_value(20);
t2.join();
}
set_exception设置异常
void get(promise<int>& p) {
int x;
cout << "please,enter an integer value = ";
cin.exceptions(ios::failbit);//throw on failbit
try {
cin >> x;
p.set_value(x);
}
catch (exception&) {
p.set_exception(current_exception());
}
}
void print(future<int>& f){
try {
int x = f.get();
cout << "value = " << x << endl;
}
catch (exception& e) {
cout << "[exception caught >> " << e.what() << "]\n";
}
}
void test03() {
promise<int> p;
future<int> f = p.get_future();
thread t1(get, std::ref(p));
thread t2(print, std::ref(f));
t1.join();
t2.join();
}
packaged_task类
packaged_task对象内部包含两个基本元素:
- 被包装的任务,即一个可调用对象
- 共享状态,用于保存任务的返回值。可以通过future对象来达到异步访问共享状态的效果
void test01() {
auto lam = [](int from,int to)->int {
for (int i = from; i != to; i--) {
cout << i << "\n";
this_thread::sleep_for(chrono::seconds(1));
}
cout << "Finished!\n";
return from - to;
};
//传递一个函数类型,返回类型(参数类型,参数类型. .. )
packaged_task<int(int, int)> task(lam);//设置packaged_task
future<int> f = task.get_future();//获得与packaged_task共享状态相关联的 future对象
thread t(std::move(task), 10, 0);//创建一个新线程完成计数任务
int x = f.get();
cout << "the lam lasted for " << x << " seconds\n";
t.join();
}
std::move转移所有权、重置packaged_task对象的共享状态(保留了之前包装的任务)
void test02() {
auto lam = [](int x) {return 3 * x; };
packaged_task<int(int)> task(lam);
future<int> f = task.get_future();
thread(std::ref(task), 100).detach();//分离 这里千万不要传递task所有权
cout << f.get() << endl;
task.reset();
f = task.get_future();
thread(std::move(task), 200).detach();//分离
cout << f.get() << endl;
}
async()
不用thread对象也可以创建线程,
#include<chrono>
bool is_prime(int x) {
for (int i = 2; i < x; ++i)
if (x%i == 0)
return false;
return true;
}
void test01() {
future<bool> f = async(is_prime, 7);
cout << "checking, please wait";
chrono::milliseconds s(1000);
while (f.wait_for(s) == future_status::timeout)
cout << " . ";
bool x = f.get();
cout << "\7 " << (x ? "is" : "is not") << " prime.\n";
}
future_status::ready
共享状态的标志已经变成ready,即Provider在共享状态上设定了值或设定了异常
future_status::timeout
超时,在规定的时间内共享状态的标志没有变成ready
future_status::deferred
共享状态包含一个deferred函数
void print(char c, int ms) {
for (int i = 0; i < 10; i++) {
this_thread::sleep_for(chrono::milliseconds(ms));
cout << c;
}
}
void test04() {
cout << " with launch::async >> \n";
future<void> f = async(launch::async, print, '*', 100);
future<void> b = async(launch::async, print, '@', 200);
f.get();
b.get();
cout << "\n\n with launch::deferred >> \n";
f = async(launch::deferred, print, '*', 100);
b = async(launch::deferred, print, '@', 200);
f.get();
b.get();
}