C++ future和promise的用法(附带实例)
C++ 程序中,线程函数是无法返回值的,线程需要使用共享数据等其他方式来实现。然而,这需要同步。
将返回值或异常传递给主线程或其他线程的另一种方式是使用 std::promise。本节将解释这个机制是如何工作的。
1) 将 promise 变量作为线程函数的一个参数,比如:
2) 在 promise 上调用 set_value() 设置值或调用 set_exception() 设置异常:
3) 将 future 与 promise 关联,并将其作为参数对其他线程函数可见,示例如下:
4) 在 future 对象上调用 get() 来获取 promise 设置的值:
5) 在调用线程中,使用 promise 上的 get_future() 来获取与之关联的 future:
为了建立这个通道,你需要先创建 promise,然后创建共享状态,稍后可通过与 promise 关联的 future 读取。
你可使用以下任意方法,来设置 promise 的结果:
1) set_value() 或 set_value_at_thread_exit() 方法用来设置返回值,后者将值保存在共享状态,但只有当线程退出时才可通过关联的 future 获取。
2) set_exception() 或 set_exception_at_thread_exit() 方法用来设置异常返回值。异常封装在 std::exception_ptr 对象中。后者将异常保存在共享状态,但只有当线程退出时才可通过关联的 future 获取。
使用 get_future() 方法,可获取与 promise 关联的 future 对象。使用 get() 方法,可从 future 中获取值。在共享状态值可用前,调用线程都将被阻塞。
future 类提供了几个方法,这些方法在共享状态值可用前,都将阻塞线程:
如果 promise 被设置了异常值,在 future 对象上调用 get() 方法将抛出异常。重写前面的示例如下,抛出异常而不是设置值:
通过这种方式建立 promise-future 通道是显式的操作,可通过 std::async() 函数来避免。它是更高层级的工具,异步运行函数,创建内部 promise 并共享状态,返回关联的 future。
将返回值或异常传递给主线程或其他线程的另一种方式是使用 std::promise。本节将解释这个机制是如何工作的。
本节使用的 promise 和 future 类在 <future> 头文件的 std 命名空间中可用。
C++ promise和future的使用方式
通过 promise 和 future,从一个线程中将值传递给另一个线程,可以这么做:1) 将 promise 变量作为线程函数的一个参数,比如:
void produce_value(std::promise<int>& p) { // simulate long running operation { using namespace std::chrono_literals; std::this_thread::sleep_for(2s); } // continued at 2. }
2) 在 promise 上调用 set_value() 设置值或调用 set_exception() 设置异常:
// continued from 1. p.set_value(42); }
3) 将 future 与 promise 关联,并将其作为参数对其他线程函数可见,示例如下:
void consume_value(std::future<int>& f) { // continued at 4. }
4) 在 future 对象上调用 get() 来获取 promise 设置的值:
// continued from 3. auto value = f.get();
5) 在调用线程中,使用 promise 上的 get_future() 来获取与之关联的 future:
std::promise<int> p; std::thread t1(produce_value, std::ref(p)); std::future<int> f = p.get_future(); std::thread t2(consume_value, std::ref(f)); t1.join(); t2.join();
C++ promise和future的工作原理
基本上,promise-future 对是通过共享状态,来帮助线程间传递值或异常的一种沟通通道。promise 是值的异步提供者,有相对应的 future 用来表示异步的返回对象。为了建立这个通道,你需要先创建 promise,然后创建共享状态,稍后可通过与 promise 关联的 future 读取。
你可使用以下任意方法,来设置 promise 的结果:
1) set_value() 或 set_value_at_thread_exit() 方法用来设置返回值,后者将值保存在共享状态,但只有当线程退出时才可通过关联的 future 获取。
2) set_exception() 或 set_exception_at_thread_exit() 方法用来设置异常返回值。异常封装在 std::exception_ptr 对象中。后者将异常保存在共享状态,但只有当线程退出时才可通过关联的 future 获取。
使用 get_future() 方法,可获取与 promise 关联的 future 对象。使用 get() 方法,可从 future 中获取值。在共享状态值可用前,调用线程都将被阻塞。
future 类提供了几个方法,这些方法在共享状态值可用前,都将阻塞线程:
- 只有当结果可用时,wait() 才会返回;
- 当结果可用或超时后,wait_for() 才会返回;
- 当结果可用或到达指定时间点时,wait_until() 才会返回。
如果 promise 被设置了异常值,在 future 对象上调用 get() 方法将抛出异常。重写前面的示例如下,抛出异常而不是设置值:
void produce_value(std::promise<int>& p) { // simulate long running operation { using namespace std::chrono_literals; std::this_thread::sleep_for(2s); } try { throw std::runtime_error("an error has occurred!"); } catch(...) { p.set_exception(std::current_exception()); } } void consume_value(std::future<int>& f) { std::lock_guard<std::mutex> lock(g_mutex); try { std::cout << f.get() << '\n'; } catch(std::exception const & e) { std::cout << e.what() << '\n'; } }在 consume_value() 函数中可以看到,get() 的调用放在 try...catch 代码块中。如果异常被捕获——在这个特定的实现中——消息将被输出到控制台。
通过这种方式建立 promise-future 通道是显式的操作,可通过 std::async() 函数来避免。它是更高层级的工具,异步运行函数,创建内部 promise 并共享状态,返回关联的 future。