std::promise, 2290, c++

std::promise is a c++ class that provides a facility to store a value or an exception to be asynchronously acquired laterly via std::future object created by std::promise object.

std::promise makes cross-thread exception possible.

std::promise object can be referenced to or std::move to sub-thread.

#include <iostream>
#include <future>
#include <thread>
#include <complex>	// std::sqrt
#include <functional>
#include <vector>

using std::string_literals::operator""s;

namespace nsa
{
	std::mutex mutex;

	class my_class
	{
	private:
		void make_value(std::promise<double> & promise, int value)
		{
			std::this_thread::sleep_for(std::chrono::seconds(2));
			if (value < 0)
				throw std::runtime_error{"Negative value is not allowed: "s + std::to_string(value)};
			promise.set_value(std::sqrt(value));
		}
	private:
		void run_value(std::promise<double> & promise, int value)
		{
			try
			{
				this->make_value(std::ref(promise), value);
			}
			catch (...)
			{
				std::exception_ptr ptr = std::current_exception();
				promise.set_exception(ptr);
			}
		}
	private:
		void be_back(std::promise<double> && promise, int value)
		{
			this->print("Be back: I will be back.");
			this->run_value(std::ref(promise), value);
		}
		void i_will(std::promise<double> & promise, int value)
		{
			this->print("I will: I will be back.");
			this->run_value(std::ref(promise), value);
		}
	public:
		void back_set(int value)
		{
			std::promise<double> promise;
			std::future<double> future = promise.get_future();
			std::jthread thread{
				std::bind(
					&nsa::my_class::be_back,
					this,
					std::placeholders::_1,
					std::placeholders::_2
				),
				std::move(promise),
				value
			};
			thread.detach();
			this->print("back_set: wait ...");
			std::this_thread::sleep_for(std::chrono::seconds(1));
			this->print("back_set: get ...");
			double r = future.get();
			this->print("back_set: get value: "s + std::to_string(r));
		}
		void i_set(int value)
		{
			std::promise<double> promise;
			std::future<double> future = promise.get_future();
			std::jthread thread{
				std::bind(
					&nsa::my_class::i_will,
					this,
					std::placeholders::_1,
					std::placeholders::_2
				),
				std::ref(promise),
				value
			};
			thread.detach();
			this->print("i_set: wait ...");
			std::this_thread::sleep_for(std::chrono::seconds(1));
			this->print("i_set: get ...");
			double r = future.get();
			this->print("i_set: get value: "s + std::to_string(r));
		}
	private:
		void back_wrap(int value)
		{
			try
			{
				this->back_set(value);
			}
			catch (const std::exception & e)
			{
				this->print("back_wrap c++ std::exception: "s + e.what());
			}
		}
		void i_wrap(int value)
		{
			try
			{
				this->i_set(value);
			}
			catch (const std::exception & e)
			{
				this->print("i_wrap c++ std::exception: "s + e.what());
			}
		}
	public:
		void run()
		{
			std::vector<std::jthread> pool;
			for (int i=-3; i<=3; ++i)
			{
				pool.emplace_back(
					std::bind(
						&nsa::my_class::back_wrap,
						this,
						std::placeholders::_1
					),
					i
				);
			}
			for (int i=-3; i<=3; ++i)
			{
				pool.emplace_back(
					std::bind(
						&nsa::my_class::i_wrap,
						this,
						std::placeholders::_1
					),
					i
				);
			}
		}
	public:
		void print(const std::string & str) const
		{
			std::unique_lock<std::mutex> lock{nsa::mutex};
			std::cout << str << std::endl;
		}
	};
}

int main()
{
	nsa::my_class object;
	object.run();
}




Jul 6, 2025





Back     Home