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

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/fengbingchun/article/details/104115489

模板类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_

GitHubhttps://github.com/fengbingchun/Messy_Test

  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在C++std::promise是一种线程间通信机制,它允许一个线程在另一个线程设置一个值。在使用std::promise时,一个线程可以将一个值传递给另一个线程,而无需等待该线程返回。具体而言,std::promise允许线程A创建一个std::future对象并将其返回给线程B,线程B可以在某个时间点通过调用std::promise的set_value()方法来设置std::future对象的值。一旦std::future对象被设置了值,线程A可以通过调用std::future对象的get()方法来获取该值。在使用std::promise时,需要注意的是,一个std::promise对象只能被设置一次值,因此在使用它时需要小心。 ### 回答2: std::promiseC++标准库的一个类,用于在线程之间传递异步操作的结果。它通常与 std::future 一起使用,通过 std::promise 传递数据给 std::future 对象,在另一个线程可以获取到该数据。 std::promise 的用法可以分为三个步骤:创建 promise 对象、获取 future 对象、设置 promise 对象的值。 首先,我们需要创建一个 promise 对象,这可以通过构造函数来完成,例如:std::promise<int> myPromise; 这样就创建了一个用于传递 int 类型数据的 promise 对象。 接下来,我们需要使用 promise 对象获取对应的 future 对象,通过调用 promise 对象的成员函数 std::promise::get_future() 来获取,例如:std::future<int> myFuture = myPromise.get_future(); 这样就获得了一个用于接收 int 类型数据的 future 对象。 最后,我们可以通过设置 promise 对象的值来传递数据给 future 对象。这可以通过调用 promise 对象的成员函数 std::promise::set_value() 来完成,例如:myPromise.set_value(42); 这样就将值 42 传递给了之前创建的 future 对象。 在另一个线程,我们可以通过调用 future 对象的成员函数 std::future::get() 来获取到设置的值,例如:int result = myFuture.get(); 这样就可以获取到之前设置的值 42。 需要注意的是,一旦 promise 对象被设置了值,就不能再次设置。如果我们不希望在某些情况下传递数据到 future 对象,可以使用 std::promise::set_exception() 来设置一个异常。 总而言之,std::promise 提供了一种方便的机制来在线程之间传递异步操作的结果,通过设置 promise 对象的值,可以在另一个线程获取到这些值,并进行相应的处理。 ### 回答3: std::promiseC++标准库的一个类模板,用于在多线程编程用来存放一个值或者一个异常的容器。它通常与std::future一起使用,将一个值或异常从一个线程传递到另一个线程。 std::promise提供了两个主要的成员函数set_value()和set_exception()来设置值和异常。当一个线程调用set_value()或set_exception()时,std::promise的状态会变为“就绪”状态。其他线程可以通过std::future对象获取std::promise的值或异常。 使用std::promise的基本步骤如下: 1. 创建一个std::promise对象,例如std::promise<int> p; 2. 创建一个std::future对象,通过std::promise的get_future()成员函数获取,例如std::future<int> f = p.get_future(); 3. 启动一个线程,该线程可以在某个时间点调用p.set_value()或p.set_exception()来设置值或异常。 4. 在需要的地方,通过std::future对象的get()成员函数获取std::promise的值或异常。 例如,通过std::promise实现一个计算线程和一个读取结果的线程的示例: ``` #include <iostream> #include <thread> #include <functional> #include <future> void calculate(std::promise<int>& resultPromise, int a, int b) { int result = a + b; resultPromise.set_value(result); } int main() { std::promise<int> resultPromise; std::future<int> resultFuture = resultPromise.get_future(); std::thread calculationThread(calculate, std::ref(resultPromise), 3, 4); // 等待计算线程完成 calculationThread.join(); // 读取结果 int result = resultFuture.get(); std::cout << "Result: " << result << std::endl; return 0; } ``` 这个示例,计算线程通过调用resultPromise.set_value()来设置结果值,读取结果的线程通过resultFuture.get()来阻塞等待结果值的返回,这样就实现了两个线程之间的值的传递和同步。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值