template< class R, class ...Args >
class packaged_task< fn(Args...)>;
packaged_task是类模板,定义于future头文件中,它包装任何种类可调用的 目标(函数、lambda表达式、std::bind表达式或其他函数对象)。
异步调用后,返回值或所抛异常被存储在一个能通过std::future对象访问的共享状态中。
最简单的理解:
将一个普通的函数对象转换为异步执行的任务
在packaged_task成员中,进行了()运算符重载,因此我们可以直接调用这个开始启动任务。
#include
#include
#include
using namespace std;
int TestFunc(int a, int b){
cout << "thread id=" << std::this_thread::get_id() << " " << __FUNCTION__ << endl;
int result = 0;
for (int i = a; i < b; i++) {
result += 3;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return result;
}
void task_func()
{
cout << "thread id=" << std::this_thread::get_id() << " " << __FUNCTION__ << endl;
//包装普通函数
std::packaged_task<int(int, int)> task(TestFunc);
//std::packaged_task task(std::bind(TestFunc, 33, 66));
future<int>result = task.get_future();
//启动任务,同步执行
task(33, 66);
//task();
cout << "task_func TestFunc(33, 66) :" << result.get() << " " << __FUNCTION__ << endl;
}
void task_thread()
{
cout << "thread id=" << std::this_thread::get_id() << " " << __FUNCTION__ << endl;
//构造时传递用于异步执行的函数指针add
packaged_task<int(int, int)> ansyc_task(TestFunc);
//从packaged_task<>获取相关的future
future<int> future = ansyc_task.get_future();
//创建线程,同时传递函数TestAdd的运行参数
thread exec_thread(move(ansyc_task), 33, 66);
//获得函数packaged_task在另一个线程中的运行结果
int ret = future.get();
//join线程,阻塞直到线程完成时返回
exec_thread.join();
cout << "TestFunc(1,20)=" << ret << " " << __FUNCTION__ << endl;
}
void task_lambda()
{
cout << "thread id=" << std::this_thread::get_id() << " " << __FUNCTION__ << endl;
//包装目标为lambda
packaged_task<int(int, int)> task([](int a, int b) { return a + b; });
//仿函数形式,启动任务
task(33, 66);
future<int> result = task.get_future();
cout << "task_lambda (33, 66) :" << result.get() << " " << __FUNCTION__ << endl;
}
int main()
{
task_func();
task_lambda();
task_thread();
return 0;
}
packaged_task不可以复制,只可以移动,所以我们需要在将它移动到执行线程之前,从它那里获取 std::future对象。
packaged_task.swap(packaged_task_other)
packaged_task.valid() // 检查std::packaged_task是否拥有一个有效的函数
packaged_task.get_future() // 获得与其封装的函数相绑定的future
packaged_task.make_ready_at_thread_exit(ex) // 执行相应的函数,其结果在线程退出时写到数据管道
packaged.reset() // 重置task的状态,并废弃以前执行的结果
std::swap(packaged_task_1, packaged_task_2) // 交换底层的task