C++ future async promise 用法详解 - promise
背景
- 不想利用async提供的线程模型
- 还想方便的获取线程运行结果
原理
- 生产者 - 消费者模型
基本函数
-
生产函数,分两步
- 设置value或者exception
- 设置shared state
template <class R&> // 设置value或者exception后,立即将shared state设置为ready void set_value (R& val); void set_exception (exception_ptr p); // 设置value或者exception后,在当前线程退出后才把shared state设置为ready void set_value_at_thread_exit (R& val); void set_exception_at_thread_exit (exception_ptr p);
-
消费函数
获取future,负责保存shared state和value/exception
template <class T> future<T> get_future();
-
其他函数
// 构造函数 promise(); promise (const promise&) = delete; promise (promise&& x) noexcept; // 只可用移动赋值运算 promise& operator= (promise&& rhs) noexcept; promise& operator= (const promise&) = delete; // swap 函数 void swap (promise& x) noexcept; template <class T> void swap (promise<T>& x, promise<T>& y) noexcept;
基本用法
-
生产者push执行结果,消费者pop执行结果
-
生产者push状态,消费者pop状态
-
单生产,单消费不会有异常;多生产/多消费需要处理异常状态
-
支持线程池的使用
#include <vector> #include <thread> #include <future> #include <numeric> #include <iostream> #include <chrono> // value 通信 void accumulate(std::vector<int>::iterator first, std::vector<int>::iterator last, std::promise<int> accumulate_promise) { int sum = std::accumulate(first, last, 0); accumulate_promise.set_value(sum); // 生产一次 } // state 通信 void do_work(std::promise<void> barrier) { std::this_thread::sleep_for(std::chrono::seconds(1)); barrier.set_value(); // 生产一次 } int main() { // value 通信 std::vector<int> numbers = { 1, 2, 3, 4, 5, 6 }; std::promise<int> accumulate_promise; // 构造 std::future<int> accumulate_future = accumulate_promise.get_future(); // 获取消费者 std::thread work_thread(accumulate, numbers.begin(), numbers.end(), std::move(accumulate_promise)); // 生产线程 std::cout << "result=" << accumulate_future.get() << '\n'; // 消费一次 work_thread.join(); // wait for thread completion // state 通信 std::promise<void> barrier; // 构造 std::future<void> barrier_future = barrier.get_future(); // 获取消费者 std::thread new_work_thread(do_work, std::move(barrier)); // 生产线程 barrier_future.wait(); // 消费一次 new_work_thread.join(); // wait for thread completion }