其实std::packaged_task并没有引入新的概念, 它是一个包装类,它包装任何
可调用 (Callable)
目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。其返回值或所抛异常被存储于能通过
std::future
对象访问的共享状态中。
正
如 std::function , std::packaged_task 是多态、具分配器的容器:可在堆上或以提供的分配器分配存储的可调用对象。
std::packaged_task本身很简单,但是却给了我们很多想象空间,这篇文章就不展开讲它的具体应用场景。我会在下一篇文章描述一下怎么利用packaged_task, 100行实现thread pool,敬请期待。
下面我们来看一下具体的定义:
std::packaged_task
定义于头文件 <future> | ||
template< class > class packaged_task; // 不定义 | (1) | (C++11 起) |
template< class R, class ...Args > | (2) | (C++11 起) |
下边是一些比较枯燥的API解释, 不喜欢看可以略过,直接看例子。
成员函数
(构造函数) | 构造任务对象 (公开成员函数) |
(析构函数) | 析构任务对象 (公开成员函数) |
operator= | 移动任务对象 (公开成员函数) |
valid | 检查任务对象是否拥有合法函数 (公开成员函数) |
swap | 交换二个任务对象 (公开成员函数) |
获取结果 | |
get_future | 返回与承诺的结果关联的 std::future (公开成员函数) |
执行 | |
operator() | 执行函数 (公开成员函数) |
make_ready_at_thread_exit | 执行函数,并确保结果仅在一旦当前线程退出时就绪 (公开成员函数) |
reset | 重置状态,抛弃任何先前执行的存储结果 (公开成员函数) |
非成员函数
std::swap(std::packaged_task) (C++11) | 特化 std::swap 算法 (函数模板) |
辅助类
std::uses_allocator<std::packaged_task> (C++11)(C++17 前) | 特化 std::uses_allocator 类型特征 (类模板特化) |
例子:
#include <iostream>
#include <future>
#include <thread>
int main()
{
// 将一个返回值为7的 lambda 表达式封装到 task 中
// std::packaged_task 的模板参数为要封装函数的类型
std::packaged_task<int()> task([](){return 7;});
// 获得 task 的 future
std::future<int> result = task.get_future(); // 在一个线程中执行 task
std::thread(std::move(task)).detach(); std::cout << "Waiting...";
result.wait();
// 输出执行结果
std::cout << "Done!" << std:: endl << "Result is " << result.get() << '\n';
}
例子2:
#include <iostream>
#include <cmath>
#include <thread>
#include <future>
#include <functional>
// 避免对 std::pow 重载集消歧义的独有函数
int f(int x, int y) { return std::pow(x,y); }
void task_lambda()
{
std::packaged_task<int(int,int)> task([](int a, int b) {
return std::pow(a, b);
});
std::future<int> result = task.get_future();
task(2, 9);
std::cout << "task_lambda:\t" << result.get() << '\n';
}
void task_bind()
{
std::packaged_task<int()> task(std::bind(f, 2, 11));
std::future<int> result = task.get_future();
task();
std::cout << "task_bind:\t" << result.get() << '\n';
}
void task_thread()
{
std::packaged_task<int(int,int)> task(f);
std::future<int> result = task.get_future();
std::thread task_td(std::move(task), 2, 10);
task_td.join();
std::cout << "task_thread:\t" << result.get() << '\n';
}
int main()
{
task_lambda();
task_bind();
task_thread();
}
输出:
task_lambda: 512
task_bind: 2048
task_thread: 1024