CodeNebula
C++11coreintermediate

std::promise (C++11 Addition)

C++11 · Modern Revolution · Compiler flag: -std=c++11

Explanation

A mechanism for a thread to set a value or exception that can be retrieved by an associated `std::future`, providing explicit control over asynchronous result delivery.

Real-World Scenario

A worker thread computes a result and delivers it to the main thread through a promise/future pair.

Quick Snippet

snippet.cpp
#include <future>
#include <thread>
std::promise<int> prom;
std::future<int> fut = prom.get_future();

std::thread t([&prom] { prom.set_value(42); });
int result = fut.get(); // 42
t.join();

Full Example

promise.cpp
// CodeNebula - C++11 Example: std::promise
// Compile: g++ -std=c++11 -Wall -Wextra -pthread -o example promise.cpp
//
// This example demonstrates:
// - std::promise to set values for associated futures
// - set_value() for normal results
// - set_exception() for error propagation
// - Promise-future channel for thread communication
// - One-shot synchronization between threads

#include <iostream>
#include <future>
#include <thread>
#include <string>
#include <stdexcept>
#include <functional>
#include <numeric>
#include <vector>

// ============================================================
// 1. Basic promise: set_value
// ============================================================
void computeAndDeliver(std::promise<int> resultPromise, int a, int b) {
    std::cout << "  Worker: computing " << a << " + " << b << std::endl;
    int result = a + b;
    resultPromise.set_value(result);  // Deliver the result
    std::cout << "  Worker: value delivered" << std::endl;
}

// ============================================================
// 2. Promise with exception
// ============================================================
void divideSafely(std::promise<double> resultPromise, double a, double b) {
    if (b == 0.0) {
        // Deliver an exception instead of a value
        resultPromise.set_exception(
            std::make_exception_ptr(
                std::runtime_error("Division by zero")
            )
        );
    } else {
        resultPromise.set_value(a / b);
    }
}

// ============================================================
// 3. Promise as a synchronization signal (void promise)
// ============================================================
void workerWithSignal(std::promise<void> readySignal) {
    std::cout << "  Worker: initializing..." << std::endl;
    // Simulate initialization work
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    std::cout << "  Worker: ready!" << std::endl;
    readySignal.set_value();  // Signal that we're ready
}

// ============================================================
// 4. Chain of promises for pipeline processing
// ============================================================
void stage1(std::promise<int> output) {
    std::cout << "  Stage 1: generating data" << std::endl;
    output.set_value(10);
}

void stage2(std::future<int> input, std::promise<int> output) {
    int val = input.get();
    std::cout << "  Stage 2: received " << val << ", doubling" << std::endl;
    output.set_value(val * 2);
}

void stage3(std::future<int> input, std::promise<std::string> output) {
    int val = input.get();
    std::cout << "  Stage 3: received " << val << ", formatting" << std::endl;
    output.set_value("Final: " + std::to_string(val));
}

int main() {
    std::cout << "=== std::promise ===" << std::endl;

    // Basic set_value
    std::cout << "\n--- Basic promise ---" << std::endl;
    std::promise<int> sumPromise;
    std::future<int> sumFuture = sumPromise.get_future();

    std::thread t1(computeAndDeliver, std::move(sumPromise), 30, 12);
    std::cout << "  Main: waiting for result..." << std::endl;
    int result = sumFuture.get();
    std::cout << "  Main: got " << result << std::endl;
    t1.join();

    // Exception delivery
    std::cout << "\n--- Exception via promise ---" << std::endl;
    std::promise<double> divPromise1;
    std::future<double> divFuture1 = divPromise1.get_future();
    std::thread t2(divideSafely, std::move(divPromise1), 10.0, 3.0);
    std::cout << "  10 / 3 = " << divFuture1.get() << std::endl;
    t2.join();

    std::promise<double> divPromise2;
    std::future<double> divFuture2 = divPromise2.get_future();
    std::thread t3(divideSafely, std::move(divPromise2), 10.0, 0.0);
    try {
        divFuture2.get();
    } catch (const std::runtime_error& e) {
        std::cout << "  10 / 0 threw: " << e.what() << std::endl;
    }
    t3.join();

    // Void promise as signal
    std::cout << "\n--- Void promise (signal) ---" << std::endl;
    std::promise<void> readyPromise;
    std::future<void> readyFuture = readyPromise.get_future();
    std::thread t4(workerWithSignal, std::move(readyPromise));
    readyFuture.get();  // Blocks until worker signals ready
    std::cout << "  Main: worker is ready, proceeding" << std::endl;
    t4.join();

    // Pipeline
    std::cout << "\n--- Pipeline with promises ---" << std::endl;
    std::promise<int> p1;
    std::promise<int> p2;
    std::promise<std::string> p3;
    auto f1 = p1.get_future();
    auto f2 = p2.get_future();
    auto f3 = p3.get_future();

    std::thread s1(stage1, std::move(p1));
    std::thread s2(stage2, std::move(f1), std::move(p2));
    std::thread s3(stage3, std::move(f2), std::move(p3));

    std::cout << "  Pipeline result: " << f3.get() << std::endl;
    s1.join();
    s2.join();
    s3.join();

    return 0;
}

// Expected output:
// === std::promise ===
//
// --- Basic promise ---
//   Main: waiting for result...
//   Worker: computing 30 + 12
//   Worker: value delivered
//   Main: got 42
//
// --- Exception via promise ---
//   10 / 3 = 3.33333
//   10 / 0 threw: Division by zero
//
// --- Void promise (signal) ---
//   Worker: initializing...
//   Worker: ready!
//   Main: worker is ready, proceeding
//
// --- Pipeline with promises ---
//   Stage 1: generating data
//   Stage 2: received 10, doubling
//   Stage 3: received 20, formatting
//   Pipeline result: Final: 20
Run command
g++ -std=c++11 -Wall -Wextra -pthread -o example promise.cpp