5.2.28 · HinglishC++ Programming

std - promise and std - future

1,887 words9 min readRead in English

5.2.28 · Coding › C++ Programming


WHY ye exist karta hai?

Jo cheez ye dono jointly manage karte hain use shared state kehte hain — ek heap-allocated control block jo (value | exception), ek ready flag, aur synchronization primitives hold karta hai.


WHAT exactly hain ye?


HOW ye under the hood kaam karta hai (first principles se derivation)

Hum API memorize nahi karte — hum use reconstruct karte hain. Ek sahi "do threads ke beech ek value bhejna" gadget mein kya hona chahiye?

  1. Result ke liye storage. Type T, plus ek alternative exception_ptr slot.
  2. Ek ready flag bool ready = false. WHY: reader ko pata hona chahiye ki data present hai ya nahi.
  3. Ek mutex m. WHY: do threads se value/flag likhna aur padhna otherwise ek data race hai (undefined behavior).
  4. Ek condition_variable cv. WHY: reader ko ready hone tak sleep karna chahiye (busy-spin nahi) aur set hone par wake hona chahiye.

Sab mila ke, ek minimal hand-built version:

template<class T>
struct SharedState {
    std::mutex m;
    std::condition_variable cv;
    bool ready = false;
    T value;
    std::exception_ptr ex;
};
 
// promise.set_value(v):
{
    std::lock_guard<std::mutex> lk(state->m);
    state->value = v;          // store
    state->ready = true;       // mark
}                              // unlock
state->cv.notify_all();        // wake the future
 
// future.get():
{
    std::unique_lock<std::mutex> lk(state->m);
    state->cv.wait(lk, [&]{ return state->ready; }); // sleep until ready
    if (state->ex) std::rethrow_exception(state->ex);
    return std::move(state->value);
}

Ye exactly wahi hai jo standard library std::promise/std::future tumhare liye karti hai — correctly, portably, aur exception transport built in ke saath.

Figure — std - promise and std - future

Worked Example 1 — basic value transfer

#include <future>
#include <thread>
#include <iostream>
 
void worker(std::promise<int> p) {
    int result = 6 * 7;          // pretend this is heavy work
    p.set_value(result);         // fulfil the promise
}
 
int main() {
    std::promise<int> prom;          // Why: create the writing end
    std::future<int>  fut = prom.get_future(); // Why: grab reading end BEFORE moving promise
 
    std::thread t(worker, std::move(prom)); // Why: promise is move-only, must std::move
 
    std::cout << fut.get() << "\n";  // Why: blocks here until worker calls set_value -> 42
    t.join();
}
  • get_future() std::move(prom) se pehle kyun? prom ko thread mein move karne ke baad, local prom empty hai; tum ab us se future nahi le sakte.
  • std::move(prom) kyun? std::promise non-copyable hai (shared state duplicate nahi ho sakta). Writing end ka sirf ek hi owner.

Worked Example 2 — exception transport karna

void worker(std::promise<int> p) {
    try {
        throw std::runtime_error("disk on fire");
        // p.set_value(1); // never reached
    } catch (...) {
        p.set_exception(std::current_exception()); // Why: capture & ship the exception
    }
}
 
int main() {
    std::promise<int> prom;
    auto fut = prom.get_future();
    std::thread t(worker, std::move(prom));
    try {
        int x = fut.get();   // Why: this re-throws the runtime_error in THIS thread
        std::cout << x;
    } catch (const std::exception& e) {
        std::cout << "caught: " << e.what() << "\n"; // -> caught: disk on fire
    }
    t.join();
}
  • Ye powerful kyun hai? Doosre thread mein throw hui exception normally std::terminate call karta hai. promise/future tumhe exception ko thread boundary ke paar move karne aur jahan tum wait kar rahe ho wahan handle karne deta hai.

Worked Example 3 — valid() aur one-shot semantics use karna

std::promise<std::string> prom;
auto fut = prom.get_future();
prom.set_value("hello");
 
std::cout << fut.valid() << "\n";  // 1  (still associated)
std::string s = fut.get();         // moves the string out
std::cout << fut.valid() << "\n";  // 0  (consumed! get() invalidated it)
// fut.get(); // Why illegal: would throw future_error(no_state)
  • get() invalidate kyun karta hai? Ye result move out karta hai; doosre get() ke paas return karne ke liye kuch nahi, isliye standard ise forbid karta hai (one-shot channel).

Common Mistakes (Steel-man + fix)


Flashcards

Promise ko future se kya link karta hai?
Ek shared (heap-allocated) shared state jo value/exception, ek ready flag, mutex aur condition_variable hold karta hai.
Promise se future kaise obtain karte hain?
prom.get_future() — exactly ek baar call karo (do baar call karne par future_error throw hota hai).
Promise ko thread mein std::move kyun karna padta hai?
std::promise move-only (non-copyable) hai; writing end ka sirf ek hi owner allowed hai.
future::get() kya karta hai?
Shared state ready hone tak block karta hai, phir value move out karta hai (ya stored exception re-throw karta hai), aur future ko invalidate kar deta hai.
Threads ke beech exception kaise transport karte hain?
Producer mein, p.set_exception(std::current_exception()); consumer ka get() use re-throw karta hai.
Agar promise set kiye bina destroy ho jaaye toh kya hota hai?
Future ka get() code broken_promise ke saath std::future_error throw karta hai.
cv.wait(lk, pred) mein predicate kyun use karte hain?
Spurious wakeups aur us case ko handle karne ke liye jahan value wait shuru hone se pehle set ho gayi ho (ready re-check karta hai).
future::wait() aur future::get() mein kya fark hai?
wait() ready hone tak block karta hai lekin consume nahi karta; get() block karta hai phir value consume (move out) karta hai.
std::shared_future kab use karte hain?
Jab multiple threads ko same result read karna ho (ye copyable hai aur get() kai baar call ho sakta hai).
Promise kitni baar set ho sakta hai?
Exactly ek baar; doosra set_value/set_exception promise_already_satisfied throw karta hai.

Recall Feynman: 12-saal ke bachche ko samjhao

Socho tumne phone par pizza order kiya. Cook tumhe ek paper receipt deta hai (future) aur apne paas kitchen ticket rakhta hai (promise). Tum apni receipt leke baith jaate ho; abhi kha nahi sakte, toh wait karte ho. Jab pizza ready hota hai, cook ticket use karke pizza counter par rakh deta hai aur bell bajata hai. Tumhari receipt tumhe use pick up karne deti hai — exactly ek pizza, ek baar. Aur agar oven mein aag lag jaaye, toh cook tumhe ek note de sakta hai "sorry, no pizza" — aur tum receipt check karte hi jaanoge. Receipt+ticket pair ensure karta hai ki tum kabhi aisa pizza nahi lo jo ready nahi hai aur kabhi same wala do baar nahi lo.


Connections

  • std::thread — worker jo concurrently run karta hai aur promise fulfil karta hai.
  • std::async and std::launch — ek higher-level wrapper jo tumhare liye future return karta hai.
  • std::packaged_task — ek callable + automatic promise wrap karta hai.
  • std::shared_futurefuture ka multi-consumer version.
  • std::condition_variable — woh primitive jiske upar future/promise build hue hain.
  • std::mutex and lock_guard — shared state ko protect karta hai.
  • Exception handling in C++exception_ptr, current_exception, rethrow_exception.
  • Move semantics and std::move — kyun promises/futures move-only hain.

Concept Map

solved by

get_future links to

jointly manage

jointly manage

calls

calls

marks

waits on

contains

contains

contains

prevents

sleeps until

enables

re-throws via

Thread A needs result from Thread B

std promise T - writing end

std future T - reading end

shared state control block

set_value or set_exception once

get blocks then reads once

mutex

condition variable

ready flag

value or exception_ptr

exception transport

data race