Ежедневный бит (е) C++ # 26, одноразовые инструменты C++ 11 производитель-потребитель, std::promise и std::future
C++ не предлагает много высокоуровневых средств синхронизации потоков и связи. Одним из немногих является пара std::promise
и std::future
.
std::promise
и std::future
реализуют одноразовую семантику производитель-потребитель.
Потребитель (std::future
) может блокироваться до тех пор, пока не будет доступен результат производителя (std::promise
), после чего можно будет получить доступ к произведенному значению.
#include <future> #include <thread> #include <iostream> #include <stdexcept> using namespace std::literals; std::promise<std::string> promise; // Future is obtained from the promise. std::future<std::string> future = promise.get_future(); auto t = std::jthread([promise = std::move(promise)] mutable { std::this_thread::sleep_for(100ms); // Set the value, this will unblock the consumer (future). promise.set_value("Hello World!"s); // If it is preferable to block until this thread finishes: // promise.set_value_at_thread_exit("Hello World!"s); }); // Will block until value awailable, // then returns the stored value: std::cout << future.get() << "\n"; // Will print: "Hello World!" // Promise/Future can also propagate exceptions: std::promise<int> other; std::future<int> will_fail = other.get_future(); auto f = std::jthread([promise = std::move(other)] mutable { try { throw std::runtime_error("Some error happened."); promise.set_value(10); // unreachable } catch (...) { promise.set_exception(std::current_exception()); // same as before we can also: // set_exception_at_thread_exit(...); } }); try { // Block until value awailable, in this case, // the exception will be propagated instead. int v = will_fail.get(); std::cout << "This will not print " << v << "\n"; } catch (const std::exception& e) { std::cout << "Propagated exception: " << e.what() << "\n"; } // Will print: "Propagated exception: Some error happened."