C++11异步操作
C++ 11 提供了异步操作相关的类,主要有std::future std::promise std::package_task
std::future
作为异步结果的传输通道,获取线程函数的返回值;
std::promise
用来包装一个值,将数据和std::future
绑定;
std::package
用来包装一个对象,将数据和future
绑定起来,以方便异步调用;
std::future
future
提供了异步查询的通道,我们可以用同步等待的方式来获取结果,可以通过查询future
的状态(future_status
)来获取异步操作的结果
enum class future_status {ready, //异步操作已经完成timeout, //异步操作超时deferred //异步操作还没开始
};
我们可以不断查询future
的状态,并比对,直到任务完成为止
std::promise
std::promise
将数据和future
绑定,为获取线程中的某个值提供便利
- 在线程函数中为
promise
赋值 - 在线程函数执行完毕后就可以通过
promise
的future
获取值
示例:
#include<iostream>
#include <string>
#include <tuple>
#include <mutex>
#include <thread>
#include <list>
#include <condition_variable>
#include <future>
using namespace std;
std::promise<int> pr;void set_value(int i)
{std::this_thread::sleep_for(std::chrono::seconds(3));pr.set_value_at_thread_exit(i);
}int main()
{std::thread t1(set_value, 90);t1.join();std::future<int> f = pr.get_future();cout << f.get() << endl;
}
std::package_task
std::package_task
包装了一个可调用对象的包装类(function ,lambda function ,bind expression…)
将函数和future
绑定起来,以便异步调用
示例:
#include<iostream>
#include <string>
#include <tuple>
#include <mutex>
#include <thread>
#include <list>
#include <condition_variable>
#include <future>
#include <functional>
using namespace std;int return_value(int i )
{cout << i << endl;return i * 10;
}
int main()
{std::packaged_task<int(int)> task(return_value);std::future<int> f = task.get_future();std::thread t(std::ref(task),4);t.join();int result = f.get();cout << result << endl;
}
std::future``std::promise``std::package_task
之间区别
std::future
提供了一个访问异步操作结果的机制,它和线程是一个级别的,属于低层次的对象。在std::future
之上的高一层是std:packaged_task
和std::promise
,它们内部都有future
以便访问异步操作结果,std::packaged_task
包装的是一个异步操作,而std:;promise
包装的是一个值,都是为了方便异步操作,因为有时需要获取线程中的某个值,这时就用std:promise
,而有时需要获一个异步操作的返回值,这时就用std:packaged_task
。那么std:promise
和std:packaged_task
之间又是什么关系呢?可以将一个异步操作的结果保存到std::promise
中。future
被promise
和package_task
用来作为异步操作或者异步结果的连接通道,用std::future
和std:.shared_future
来获取异步调用的结果。future
是不可拷贝的,只能移动,shared_future
是可以拷贝的,当需要将future
放到容器中则需要用shared_future
,
package_task
和 shared_future
的基本用法如下:
#include<iostream>
#include <string>
#include <tuple>
#include <mutex>
#include <thread>
#include <list>#include <condition_variable>
#include <future>
#include <functional>
using namespace std;int func(int x)
{return x + 1;
}int main()
{std::packaged_task<int(int)> task(func);std::future<int> fut = task.get_future();std::thread(std::move(task), 2).detach();int value = fut.get();cout << value << endl;vector<std::shared_future<int >> v;std::shared_future<int> f = std::async(std::launch::async, [](int a, int b) {return a + b; }, 2, 3);v.push_back(f);std::cout << v[0].get() << endl;}
有点绕啊…
std::async
std::async
可以直接用来创建异步的task,异步操作结果也保存在future
中,获取结果时future.get()
,
如果不关注异步任务的结果,只是简单地等待任务完成,则调用future.wait()
方法
第一个参数f
是创建线程的策略
std::launch::async
:在调用async
时就开始创建线程std::launch::deferred
:延迟方式创建线程.调用async
时不创建线程,调用future
函数的get()
或者wait()
时才创建