0
0
CppHow-ToBeginner · 3 min read

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::move can 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::promise to send a value or exception to a std::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() or future.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.