C++11中std::promise的使用

9 篇文章 4 订阅

C++11中的std::promise是个模板类。一个std::promise对象可以存储由future对象(可能在另一个线程中)检索的T类型的值或派生自std::exception的异常,并提供一个同步点。

在构造std::promise对象时,该对象与新的共享状态(shared state)关联。通过调用std::promise的get_future函数,可以将该共享状态与std::future对象关联。调用之后,两个对象共享相同的共享状态:(1).std::promise对象是异步提供程序(asynchronous provider),应 在某个时刻为共享状态设置一个值。(2).std::future对象是个异步返回对象,可以检索共享状态的值,并在必要时等待其准备就绪。

std::promise used to communicate objects between thread. The class template std::promise provides a facility to store a value or an exception that is later acquired asynchronously via a std::future object created by the std::promise object. Note that the std::promise object is meant to be used only once.

共享状态的生存期至少要持续到与之关联的最后一个对象释放或销毁为止。

std::future介绍参考:https://blog.csdn.net/WHEgqing/article/details/121182552

模板类std::promise成员函数包括:

  1. 构造函数:(1).默认构造函数:通过访问新的空共享状态来初始化对象(The object is initialized with access to a new empty shared state)。(2).带allocator的构造函数。(3).禁用拷贝构造。(4).支持移动构造。

  2. 析构函数:(1).放弃(abandon)共享状态并销毁promise对象。(2).如果有其它future对象关联到同一共享状态,则共享状态本身不会被销毁。(3).如果promise对象在共享状态准备就绪前被销毁,则共享状态自动准备就绪并包含一个std::future_error类型的异常。

  3. get_future函数:(1).返回一个与promise对象的共享状态关联的std::future对象。(2).一旦准备就绪,返回的std::future对象就可以访问promise对象在共享状态上设置的值或异常。(3).每个promise共享状态只能被一个std::future对象检索(Only one future object can be retrieved for each promise shared state)。(4).调用此函数后,promise应在某个时候使其共享状态准备就绪(通过设置值或异常),否则将在销毁时自动准备就绪并包含一个std::future_error类型的异常。

  4. operator=:(1).禁用拷贝赋值。(2).支持移动赋值。

  5. set_exception:将异常指针存储进共享状态即设置共享状态的异常指针,准备就绪。

  6. set_exception_at_thread_exit:设置共享状态的异常指针,但并不将该共享状态的标志设置为ready,当线程退出时,该promise对象会自动设置为ready (Stores the exception pointer p in the shared state without making it ready immediately. Instead, it will be made ready automatically at thread exit, once all objects of thread storage duration have been destroyed)。

  7. set_value:(1).将值存储进共享状态即设置共享状态的值,准备就绪。(2).set_value(void)只是简单使共享状态就绪而无须设置任何值。

  8. set_value_at_thread_exit:设置共享状态的值,但并不将该共享状态的标志设置为ready,当线程退出时,该promise对象会自动设置为ready(Stores val as the value in the shared state without making it ready immediately. Instead, it will be made ready automatically at thread exit, once all objects of thread storage duration have been destroyed)。

  9. swap/非成员模板函数swap:交换共享状态。

详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,部分作了调整,详细内容介绍可以参考对应的reference:

#include "future.hpp"
#include <iostream>
#include <future>
#include <chrono>
#include <utility>
#include <thread>
#include <functional>
#include <memory>
#include <exception> 
#include <numeric>
#include <vector>
 
namespace future_ {
 
///
// reference: http://www.cplusplus.com/reference/future/promise/
int test_promise_1()
{
 
{ // constructor/get_future/set_value
		std::promise<int> foo; // create promise
		std::promise<int> bar = std::promise<int>(std::allocator_arg, std::allocator<int>());
		std::future<int> fut = bar.get_future(); // engagement with future
		//std::future<int> fut2 = bar.get_future(); // crash, 每个promise共享状态只能被一个std::future对象检索或关联
		//std::future<int> fut = foo.get_future();
		auto print_int = [&fut]() { int x = fut.get(); fprintf(stdout, "value: %d\n", x); };
		std::thread th1(print_int); // send future to new thread
		bar.set_value(10); // fulfill promise(synchronizes with getting the future)
		//bar.set_value(10); // crash, 每个promise的set_value仅能被调用一次
		//foo.set_value(10);
		th1.join();
}
 
{ // operator =
	std::promise<int> prom;
	auto print_promise = [&prom]() {
		std::future<int> fut = prom.get_future();
		int x = fut.get();
		std::cout << "value: " << x << '\n';
	};
 
	std::thread th1(print_promise);
	prom.set_value(10);
	th1.join();
 
	prom = std::promise<int>(); // reset, by move-assigning a new promise
	std::thread th2(print_promise);
	prom.set_value(20);
	th2.join();
}
 
{ // set_exception
	std::promise<int> prom;
	std::future<int> fut = prom.get_future();
 
	auto get_int = [&prom]() {
		int x;
		std::cout << "Please, enter an integer value: ";
		std::cin.exceptions(std::ios::failbit); // throw on failbit
		try {
			std::cin >> x; // sets failbit if input is not int
			prom.set_value(x);
		} catch (std::exception&) {
			prom.set_exception(std::current_exception());
		}
	};
 
	auto print_int = [&fut]() {
		try {
			int x = fut.get();
			std::cout << "value: " << x << '\n';
		} catch (std::exception& e) {
			std::cout << "[exception caught: " << e.what() << "]\n";
		}
	};
 
	std::thread th1(print_int);
	std::thread th2(get_int);
 
	th1.join();
	th2.join();
}
 
	return 0;
}
 
///
// reference: https://en.cppreference.com/w/cpp/thread/promise
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);  // Notify future
}
 
void do_work(std::promise<void> barrier)
{
	std::this_thread::sleep_for(std::chrono::seconds(1));
	barrier.set_value();
}
 
int test_promise_2()
{
	// Demonstrate using promise<int> to transmit a result between threads.
	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));
 
	// future::get() will wait until the future has a valid result and retrieves it.
	// Calling wait() before get() is not needed
	//accumulate_future.wait();  // wait for result
	std::cout << "result=" << accumulate_future.get() << '\n';
	work_thread.join();  // wait for thread completion
 
	// Demonstrate using promise<void> to signal state between threads.
	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();
 
	return 0;
}
 
///
// reference: https://en.cppreference.com/w/cpp/thread/promise/set_value_at_thread_exit
int test_promise_3()
{
#ifdef _MSC_VER
	// set_value_at_thread_exit
	using namespace std::chrono_literals;
	std::promise<int> p;
	std::future<int> f = p.get_future();
	std::thread([&p] {
		std::this_thread::sleep_for(1s);
		p.set_value_at_thread_exit(9); // gcc 4.9 don't support this function
	}).detach();
 
	std::cout << "Waiting..." << std::flush;
	f.wait();
	std::cout << "Done!\nResult is: " << f.get() << '\n';
#endif
 
	return 0;
}
 
} // namespace future_
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值