Futures, Promises, and Asynchronous Tasks
Concurrency and Multithreading

7.4 Futures, Promises, and Asynchronous Tasks

Spawning raw threads using std::thread is excellent for background operations, but it has a massive limitation: it is difficult to return values from the thread. You would have to manually manage shared variables, mutexes, and signals.

C++ solves this by providing asynchronous tasks, futures, and promises.

Asynchronous Tasks with `std::async`

The easiest way to run a function in the background and retrieve its return value is std::async (defined in the <future> header). It launches the task and returns a std::future object:

#include <iostream>
#include <future>

int calculateSum(int a, int b) {
    return a + b;
}

int main() {
    // Launch calculateSum in the background
    std::future<int> resultFuture = std::async(calculateSum, 100, 200);

    // You can do other work here while the calculation runs!

    // Retrieve the value. If the calculation is not done, this blocks and waits.
    int sum = resultFuture.get();
    std::cout << "Result: " << sum << '\n';
    return 0;
}
Returning values from background tasks using futures.

Futures and Promises: The Value Channel

If you want finer control, you can separate the transmission channel using std::promise and std::future. A promise is the write end of a channel, and a future is the read end. This allows you to pass a value from a background worker thread back to the main thread:

#include <iostream>
#include <thread>
#include <future>

void workerTask(std::promise<int> valPromise) {
    // Perform calculations...
    int result = 42;
    valPromise.set_value(result); // Send the value through the channel
}

int main() {
    std::promise<int> myPromise;
    std::future<int> myFuture = myPromise.get_future();

    std::thread t{workerTask, std::move(myPromise)};
    
    std::cout << "Value from thread: " << myFuture.get() << '\n';
    t.join();
    return 0;
}
Sending values from threads using promises.

* The Restaurant Buzzer Metaphor: Using futures is like ordering food at a restaurant counter. You pay, and they hand you a small buzzer (a future). You do not stand at the counter waiting (busy waiting). You go sit down, check your phone, and relax. When the food is ready, the kitchen triggers the signal (satisfies the promise), your buzzer flashes, and you retrieve your meal (future.get()).

Finished reading this lesson?