本节讨论c++11中std::packaged_task的特性与使用方法
std::packaged_task<>
std::packaged_task<>是一个类模板,代表一个异步任务。封装了
1、可调用实体,即函数,lambda函数或函数对象
2、一个共享状态,通过关联的回调来存储返回的值或抛出的异常。
假设我们有一个现有的函数从数据库中提取数据并返回,
//从DB获取数据
std::string gtDataFromDB(std::string token){
//Do some stuff to fetch the data
std::string data = "Data fetched from DB by filter :: + token;
return data;
}
******************************************
但是,如果我们使用std::packaged_task<>,则可以避免创建std::promise和更改函数代码。
使用packaged_task<>创建异步任务
std::packaged_task<>可以包装一个标准函数,使其适用于作为异步功能运行。
当std::packaged_task<>在一个单独的线程中运行时,它会调用相关的回调函数,并将返回值或异常存储在其内部共享状态中。该值可以通过std :: future <>对象在其他线程或主函数中访问。
从上面提到的函数创建一个packaged_task<>,运行于独立的线程并从其future<>对象获取返回值。
创建std::packaged_task<> 对象
std::packaged_task<>对象是一个类模板,因此我们需要将模板参数传递给packaged_task<>,即可调用函数的类型。
//创建封装了回调函数的packaged_task<>
std::packaged_task task(getDataFromDB);
//从packaged_task<>获取相关future<>
std::future result = task.get_future();
std::packaged_task<>可移动,但是不可复制,所以我们需要将它传递给线程
//传递packaged_task<>给线程以异步运行
std::thread th(std::move(task), "Arg");
由于packaged_task只可以移动,不可以复制,因此我们在将它移动到线程之前从它那里取出了
std::future<>对象。
//获取packaged_task<>返回的结果,即getDataFromDB()返回的值。
std::string data = result.get();
get()函数将会阻塞调用线程,直到有可调用的实体返回,并且std::packaged_task<>将数据设置为其可共享的状态。
完整的例子如下:
#include
#include
#include
#include
//从DB获取数据
std::string getDataFromDB(std::string token) {
//获取数据
std::string data = "Data fetched from DB by Filter :: " + token;
return data;
}
int main() {
//创建封装回调函数的packaged_task<>
std::packaged_task task(getDataFromDB);
//从packaged_task<>获取相关的future<>
std::future result = task.get_future();
//将packaged_task传递给线程以异步运行
std::thread th(std::move(task), "Arg");
//join线程,阻塞直到线程完成时返回
th.join();
//获取packaged_task<>的结果,即getDataFromDB()的返回值
std::string data = result.get();
std::cout << data << std::endl;
return 0;
}
输出:
Data fetched from DB by Filter :: Arg
使用lambda函数创建packaged_task
#include
#include
#include
#include
int main() {
//创建封装了lambda函数的packaged_task<>
std::packaged_task task([](std::string token) {
std::string data = "Data From " + token;
return data;
});
//从packaged_task<>获取相关的future<>
std::future result = task.get_future();
//将packaged_task传递给线程以异步运行
std::thread th(std::move(task), "Arg");
//join线程,阻塞直到线程完成时返回
th.join();
//获取packaged_task<>的结果,即getDataFromDB()的返回值
std::string data = result.get();
std::cout << data << std::endl;
return 0;
}
输出:
Data fetched from DB by Filter :: Arg
#include
#include
#include
#include
//从DB获取数据的函数对象
struct DBDataFetcher {
std::string operator ()(std::string token) {
std::string data = "Data From " + token;
return data;
}
};
int main() {
//使用函数对象创建packaged_task
std::packaged_task task(std::move(DBDataFetcher()));
//从packaged_task<>获取相关的future<>
std::future result = task.get_future();
//将packaged_task传递给线程以异步运行
std::thread th(std::move(task), "Arg");
//join线程,阻塞直到线程完成时返回
th.join();
//获取packaged_task<>的结果,即getDataFromDB()的返回值
std::string data = result.get();
std::cout << data << std::endl;
return 0;
}
输出:
Data fetched from DB by Filter :: Arg