C++11异步编程给我们提供了多种类使用,接下来我来一一小记
promise和future
**这两个是一对,失去了一个,另一个没有存在的意义,为什么这么说呢,因为他两维护一个共享状态。**可以这么理解:
cpp
//动态开辟的共享块
block
{
返回值,
条件变量,
锁
flag//标记bloc是否被设置过返回值
... ...
}
future
{
block* ptr;
}
promise
{
block* ptr;
}
promise可以给block中的返回值设置值,而future可以从block中拿取返回值,一但futrue发现flag为false就在条件变量上阻塞等待,直到返回值被设置。
没错,这两货组合起来就是一个获取线程返回值的作用,很简单。有了他两,你就可以把promise传给子线程,把future给主线程(promise可以构造出一个futrue哦),让子线程设置一些值,然后把主线程只要futrue.get()即可。这样可以实现子线程返回值获取以及控制子线程终止与否。
至于共享块的销毁,你可以认为是类似于RAII的思想。
注意:
- future和promise不可以拷贝
- future的get方法只能调用一次,调用第二次的话就会崩溃。
- promise只能set_value一次,第二次会抛异常
- 如果想让多个线程都看到某一个线程的指示,则可以用future的share方法获取到shared_future对象,这个对象可以拷贝,可以多次get
packaged_task
有了promise和futrue,我们可以获取线程返回值,那么我们就可以这样写代码:
cpp
int func(promise<int>& p)
{
int a = 2;
int b = 3;
p.set_value(a+b);
return a + b;
}
int main()
{
promise<int> x;
future<int> ret = x.get_future();
thread t(func,ref(x));
t.join();
cout << ret.get() << endl;
}
这样是不是有些复杂呢,对,所以才有了packaged_task,packaged_task就是把用户函数和promise和futrue封装起来,返回值自动被设置到promise中:
cpp
int func(int i)
{
return i;
}
int main()
{
packaged_task<int(int)> task(func);
future<int> ret = task.get_future();
thread t(move(task),5);
t.join();
cout << ret.get() << endl;
}
async
所以async是什么呢?他又是一个大封装,使用这个函数,不用创建线程,不用管什么promise:
cpp
int func(int i)
{
return i;
}
int main()
{
future<int> ret = async(func,5);
cout << ret.get() << endl;
}
另外async可以延迟执行,async(lanuch::deffered,... ... ),调用get的时候才开始执行