How to Use Future and Promise in C++ for Asynchronous Programming
In C++,
std::promise is used to set a value or exception that a std::future will receive asynchronously. You create a std::promise, get its associated std::future, and then pass the future to the consumer while the producer sets the value via the promise.Syntax
std::promise<T> is used to store a value or exception that will be passed to a std::future<T>. The future is obtained by calling get_future() on the promise.
std::promise<T> promise;- creates a promise object.std::future<T> future = promise.get_future();- gets the future linked to the promise.promise.set_value(value);- sets the value to be retrieved by the future.future.get();- waits for the value and returns it.
cpp
std::promise<int> promise; std::future<int> future = promise.get_future(); // In producer thread: promise.set_value(42); // In consumer thread: int result = future.get();
Example
This example shows how a producer thread sets a value using std::promise and a consumer thread waits for it using std::future. It demonstrates basic communication between threads.
cpp
#include <iostream> #include <thread> #include <future> void producer(std::promise<int> prom) { std::this_thread::sleep_for(std::chrono::seconds(1)); prom.set_value(100); // Set the value after some work } int main() { std::promise<int> prom; std::future<int> fut = prom.get_future(); std::thread prod_thread(producer, std::move(prom)); std::cout << "Waiting for value from producer...\n"; int value = fut.get(); // Wait and get the value std::cout << "Received value: " << value << "\n"; prod_thread.join(); return 0; }
Output
Waiting for value from producer...
Received value: 100
Common Pitfalls
- Calling
get()on a future more than once causes an error because the value is moved. - Not setting a value or exception on the promise leads to the future waiting forever (deadlock).
- Passing the promise by value instead of by
std::movecan cause unexpected behavior. - Setting a value on a promise after the future is already retrieved or after setting a value once causes exceptions.
cpp
/* Wrong: promise copied instead of moved, may cause runtime error */ std::promise<int> prom; std::future<int> fut = prom.get_future(); std::thread t([](std::promise<int> p) { p.set_value(10); // This is a copy, original promise not set }, prom); // wrong: should use std::move(prom) t.join(); /* Right: move the promise to thread */ std::promise<int> prom2; std::future<int> fut2 = prom2.get_future(); std::thread t2([](std::promise<int> p) { p.set_value(20); }, std::move(prom2)); t2.join();
Quick Reference
Summary tips for using std::future and std::promise:
- Use
std::promiseto send a value or exception to astd::future. - Always move the promise when passing to another thread.
- Call
get()on the future once to retrieve the value. - Set a value or exception on the promise exactly once.
- Use
future.wait()orfuture.get()to wait for the result.
Key Takeaways
Use std::promise to set a value that std::future will receive asynchronously.
Always move std::promise when passing it to another thread to avoid copies.
Call get() on std::future once to retrieve the promised value or exception.
Never forget to set a value or exception on the promise to avoid deadlocks.
std::future and std::promise enable safe communication between threads.