C++ future async promise 用法详解 - packaged_task
packaged_task
背景
- 启发于function pointer
- 采用类似 promise 的设计
- 方便的获取线程运行结果
原理
- 生产者 - 消费者模型
基本函数
-
生产函数,分两步
- 设置value或者exception
- 设置shared state
// 设置value或者exception后,立即将shared state设置为ready void operator()(Args... args); // 设置value或者exception后,在当前线程退出后才把shared state设置为ready void make_ready_at_thread_exit (args... args);
-
消费函数
获取future,负责保存shared state和value/exception
template <class T> future<T> get_future();
-
其他函数
// 构造函数,可采用any Callable target (function, lambda expression, bind expression, or another function object) packaged_task() noexcept; template <class Fn> explicit packaged_task (Fn&& fn); packaged_task (packaged_task&) = delete; packaged_task (packaged_task&& x) noexcept; // 只可用移动赋值运算 packaged_task& operator= (packaged_task&& rhs) noexcept; packaged_task& operator= (const packaged_task&) = delete; // swap 函数 void swap (packaged_task& x) noexcept; template <class Ret, class... Args> void swap (packaged_task<Ret(Args...)>& x, packaged_task<Ret(args...)>& y) noexcept; // Reset 函数,效果相当于重新构造 void reset(); // 是否有 callable target bool valid() const noexcept;
基本用法
-
生产者post task,自定义task执行,消费者pop 状态
-
单生产,单消费不会有异常;多生产/多消费需要处理异常状态
-
支持线程池的使用
#include <iostream> #include <cmath> #include <thread> #include <future> #include <functional> 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::cout << "task valid:\t" << task.valid() << '\n'; std::future<int> result = task.get_future(); task(2, 9); std::cout << "task_lambda:\t" << result.get() << '\n'; task.reset(); std::future<int> result2 = task.get_future(); task(2, 10); std::cout << "task_lambda:\t" << result2.get() << '\n'; task.reset(); std::future<int> result3 = task.get_future(); new std::thread([&](){ task.make_ready_at_thread_exit(2, 11); }); std::cout << "task_lambda:\t" << result3.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); // thread 支持 packaged_task 构造 task_td.join(); std::cout << "task_thread:\t" << result.get() << '\n'; } int main() { task_lambda(); task_bind(); task_thread(); }