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