Worked examples — std - promise and std - future
5.2.28 · D3· Coding › C++ Programming › std - promise and std - future
Shuru karne se pehle, poori cheez ka ek picture taaki baad ke har example isi par point kar sake. Ek promise aur ek future ek single heap block share karte hain — the shared state.

Figure ko left se right padhо. Magenta box left mein std::promise hai — writing end. Violet box right mein std::future hai — reading end. Top par dashed navy arrow prom.get_future() hai: ek baar call kiya jaata hai, aur reading end ko shared block ka link deta hai. Orange box bottom mein shared state hai, jo heap par rehta hai, aur chaar cheezein hold karta hai: value ya exception ke liye ek slot, ek ready flag, aur do synchronization tools — ek mutex (ise m kaho, ek lock jo ensure karta hai ki sirf ek thread box ko ek waqt touch kare) aur ek condition variable (ise cv kaho, ek "waiting bench" jis par ek thread so sakta hai jab tak use jagaya na jaaye). Magenta arrow set_value / set_exception hai jo box mein ek baar likhta hai; violet arrow get() hai jo isse ek baar padhta hai. Niche ke har example mein in do arrows ke along ek alag journey hai.
Us picture ke do identifiers baar baar aate rahenge, isliye hum inhe abhi, ek baar, naam dete hain:
- ==
m== — the mutex (from mutex): ek lock jo guarantee karta hai ki sirf ek thread box ko kisi bhi waqt read ya write kare, taaki koi data race na ho. - ==
cv== — the condition variable (from condition_variable): woh bench jis par ek threadget()ke andar sota hai jab takset_valueuse jagaaye. Ek ==lk== basmpar ekunique_lockhai — woh handle jo ek thread rakhta hai jab wohcvpar sota hai, sone ke dauran automatically release hota hai aur jagane par re-acquire hota hai.
The scenario matrix
promise/future ka har use inhi cells mein se ek mein fall karta hai. Columns ko socho "kya likha gaya" aur rows ko socho "timing / kaun padhta hai".
| Cell | Situation | Future ka get() kya karta hai |
|---|---|---|
| A. Value, reader waits | Producer value set karta hai; consumer pehle se get() mein block hai |
Sota hai, jagaya jaata hai, value return karta hai |
| B. Value, value-set-first | Producer value pehle set karta hai, consumer baad mein get() call karta hai |
Instantly return karta hai — koi sleep nahi |
| C. Exception transported | Producer ek exception store karta hai | get() consumer thread mein use re-throw karta hai |
| D. Broken promise | Producer kuch set kiye bina destroy ho jaata hai | get() future_error(broken_promise) throw karta hai |
| E. One-shot violation | Consumer get() do baar call karta hai, ya get_future() do baar |
future_error(no_state / future_already_retrieved) throw karta hai |
| F. Zero / degenerate payload | promise<void> — ek pure "done" signal, koi data nahi |
get() kuch return nahi karta, bas unblock karta hai |
| G. Multiple readers | Kai threads ko ek hi result dekhna hai | Plain future fail karta hai (one-shot); [[std - shared_future |
| H. Limiting: timeout | Consumer forever wait nahi kar sakta | wait_for ek status return karta hai, get() ready hone tak avoid kiya jaata hai |
| I. Real-world word problem | Do heavy computations parallel mein chalti hain, main thread dono sum karta hai | Do mailboxes, do get()s |
| J. Exam twist | Chained: packaged_task ek future feed karta hai; promise kahan hai? |
Task hi writing end hai |
Niche ke nau examples har cell A–J ko hit karte hain. Har ek apni cell ka naam leta hai.
Example 1 — Cell A: value, reader pehle se wait kar raha hai
Forecast: printed number guess karo, aur guess karo ki
mainsoya ya busy-spin kiya.
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
void worker(std::promise<int> p) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
p.set_value(6 * 7); // Step 3
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future(); // Step 1
std::thread t(worker, std::move(prom)); // Step 2
std::cout << fut.get() << "\n"; // Step 4
t.join();
}- Move se pehle
get_future(). Yeh step kyun? Jab hum step 2 meinstd::move(prom)karte hain to localpromempty ho jaata hai; tab use future ke liye poochna throw karega. Pehle reading end grab karo. - Thread mein
std::move(prom). Yeh step kyun?std::promisemove-only hai (dekho Move semantics and std::move); copy karne se ek shared state ke liye do writers ban jaate. - Sleep ke baad
set_value(6 * 7). Yeh step kyun? Yeh value likhta hai,readyflag flip karta hai, aurcvpar kisi bhi waiter ko jagaata hai — bilkul parent ke hand-built version meinset_valueblock jaisa. fut.get(). Yeh step kyun?main50 ms khatam hone se pehle yahan pahunch jaata hai, isliye shared state ready nahi hai.get()mainko condition variablecvpar so deta hai (busy loop nahi), aur CPU free rehta hai jab tak step 3 use jagaaye.
Verify: printed value hai. Timing sanity:
main~50 ms se pehle print nahi kar sakta, jo prove karta hai ki woh genuinely blocked tha aur stale zero nahi padh raha tha.
Example 2 — Cell B: reader ke wait karne se pehle value set ho jaati hai
Forecast: kya
get()instantly return karega, forever hang karega, ya throw karega?
std::promise<int> prom;
auto fut = prom.get_future();
prom.set_value(100); // ready flag yahan true flip hota hai
int x = fut.get(); // ready already true hone KE BAAD call hota haiset_value(100)pehle run hota hai. Yeh step kyun? Yehready = trueset karta hai aurcvparnotify_all()call karta hai. Koi wait nahi kar raha abhi, isliye notify kisi ko nahi jagaata — aur yeh theek hai.fut.get()baad mein run hota hai. Yeh step kyun? Parent ke predicatecv.wait(lk, []{ return ready; })ko yaad karo — jahancvcondition variable hai aurlkwoh lock hai jo thread sote waqt hold karta hai (dono upar overview mein naam diye gaye hain). Kyunkireadypehle se true hai, predicate sone se pehle satisfy ho jaata hai, isliyewaitbinacvko kabhi touch kiye immediately return kar deta hai. Ek missed notify harmless hai — predicate, signal nahi, source of truth hai.
Verify:
x == 100, zero blocking ke saath return hua. Yehi reason hai standard library predicate wait use karti hai, barewait(lk)nahi.
Example 3 — Cell C: threads ke across ek exception transport karna
Forecast: kya program crash karega, ya
mainmessage catch kar lega?
void worker(std::promise<int> p) {
try {
throw std::runtime_error("disk on fire");
} catch (...) {
p.set_exception(std::current_exception()); // Step 1
}
}
int main() {
std::promise<int> prom;
auto fut = prom.get_future();
std::thread t(worker, std::move(prom));
try {
int x = fut.get(); // Step 2
std::cout << x;
} catch (const std::exception& e) {
std::cout << "caught: " << e.what() << "\n"; // Step 3
}
t.join();
}set_exception(std::current_exception()). Yeh step kyun?std::current_exception()currently in-flight exception ko grab karke isseexception_ptrke roop mein package karta hai. Hum ise value ki jagah shared state ke exception slot mein store karte hain. (Dekho Exception handling in C++.)fut.get(). Yeh step kyun? Jab shared state mein ek exception ho,get()return nahi karta — wohrethrow_exceptioncall karta hai, wahi same exception object yahanmainke thread mein re-raise karta hai.catch. Yeh step kyun? Kyunki exceptionget()call par re-throw hui thi, iske around ek ordinarytry/catchkaam karta hai. Thread boundary ghum gayi.
Verify: output exactly
caught: disk on firehai, aur program terminate nahi karta. Sanity check: sirf exception slot use hua —set_valuekabhi call nahi hua, isliye koi half-written value nahi hai.
Example 4 — Cell D: the broken promise
Forecast: kya
get()forever hang karega (deadlock), ya ek specific error throw karega?
void worker(std::promise<int> p) {
// oops: koi set_value nahi, koi set_exception nahi — p yahan destroy ho jaata hai
}
int main() {
std::promise<int> prom;
auto fut = prom.get_future();
std::thread t(worker, std::move(prom));
t.join();
try {
int x = fut.get(); // Step 2
std::cout << x;
} catch (const std::future_error& e) {
std::cout << e.code().value() << "\n"; // Step 3
}
}- Promise unset destroy hoti hai. Yeh kyun matter karta hai? Standard kehta hai: agar promise ka shared state abandon ho jaaye (destructor bina value aur bina exception ke run kare), to destructor automatically
future_errorwith codebroken_promisestore karta hai aur state ko ready mark karta hai. Yeh ek safety net hai taaki reader kabhi deadlock na kare. fut.get(). Yeh step kyun? State ready hai (auto-stored error ki wajah se), isliyeget()unblock ho jaata hai — lekin woh ek exception hold karta hai, isliyefuture_errorre-throw karta hai.- Catch karke
e.code()inspect karo. Yeh step kyun? Confirm karta hai ki error classbroken_promisehai, kuch aur nahi.
Verify:
get()throw karta hai, woh hang nahi karta. Library ki guarantee: ek unset promise phir bhi apne future ko jagaata hai,broken_promiseke saath. Isliye tumhare producer mein har path ya toset_valueyaset_exceptionzaroor kare.
Example 5 — Cell E: one-shot violations (do get()s, do get_future()s)
Forecast: har abuse ke liye, kaun sa call throw karta hai aur
fut.valid()use se just pehle kya read karta hai?
// Abuse (a): do get_future() calls
std::promise<std::string> prom;
auto f1 = prom.get_future();
// auto f2 = prom.get_future(); // THROWS: future_already_retrieved
// Abuse (b): do get() calls
prom.set_value("hello");
std::cout << f1.valid() << "\n"; // Step 2 -> 1
std::string s = f1.get(); // Step 3 : string ko move out karta hai
std::cout << f1.valid() << "\n"; // Step 4 -> 0
// f1.get(); // Step 5 THROWS: no_state- Doosra
get_future()(abuse a). Illegal kyun? Shared state ek reading end ko diya ja sakta hai. Doosra retrieval do futures ko ek value ke liye ladhate hua create kar deta, isliyefuture_already_retrievedthrow karta hai. - Pehle
get()se pehlevalid(). Yeh step kyun?valid()poochta hai "kya main abhi bhi ek shared state se attached hoon?" Yahan woh1(true) hai — attached aur unread. - Pehla
get(). Yeh step kyun? Woh string ko shared state se move karke future ko detach kar deta hai. get()ke baadvalid(). Yeh step kyun? Ab0(false) — future consume ho chuka hai aur koi state hold nahi karta.- Doosra
get()(abuse b). Illegal kyun? Koi state bacha nahi, isliye return karne ke liye kuch nahi,future_error(no_state)throw karta hai. Agar tumhe kai reads chahiye, to shared_future mein convert karo (Example 8).
Verify:
valid()1phir0print karta hai, single legalget()ko bracket karta hai. Yeh woh cheap flag hai jo batata hai ki koiget()abhi allowed hai ya nahi.
Example 6 — Cell F: zero / degenerate payload, promise<void>
Forecast:
set_value()binaTke kaisa lagta hai, aurget()kya return karta hai?
#include <future>
#include <thread>
#include <iostream>
int main() {
std::promise<void> done; // T is void: koi storage slot nahi
std::future<void> fut = done.get_future();
std::thread t([p = std::move(done)]() mutable {
// ... setup work karo ...
p.set_value(); // Step 2 : koi argument nahi!
});
fut.get(); // Step 3 : void return karta hai, bas unblock karta hai
std::cout << "proceeding\n";
t.join();
}promise<void>. Yeh step kyun? Jab koi result nahi hota, value slot kuch nahi ban jaata.readyflag, mutexmaur condition variablecvabhi bhi wahan hain — signalling machinery hi chahiye thi, data nahi.- Empty parentheses ke saath
p.set_value(). Yeh step kyun?voidmein store karne ke liye koi object nahi, isliyeset_valuepure "flip ready and notify" operation hai. voidreturn karta huafut.get(). Yeh step kyun? Woh abhi bhi ready hone tak block karta hai, phir kuch return nahi karta. Yeh do threads ke beech ek clean one-shot barrier hai — condition_variable jaisi hi guarantees lekin plumbing hidden.
Verify: conceptually,
promise<void>= value cell remove, ready/mutex/cv retain."proceeding"sirf worker keset_value()ke baad print hota hai, jo prove karta hai ki empty-payload signal abhi bhi synchronize karta hai.
Example 7 — Cell H: limiting case, wait_for ke saath ek deadline
Forecast: 100 ms wait karne ke baad,
wait_forkya kehta hai —ready,timeout, yadeferred?
using namespace std::chrono;
std::promise<int> prom;
auto fut = prom.get_future();
std::thread t([p = std::move(prom)]() mutable {
std::this_thread::sleep_for(milliseconds(300)); // slow producer
p.set_value(7);
});
auto status = fut.wait_for(milliseconds(100)); // Step 1
if (status == std::future_status::timeout) {
std::cout << "gave up waiting\n"; // Step 2
} else if (status == std::future_status::ready) {
std::cout << fut.get() << "\n";
}
t.join();wait_for(100ms). Yeh step kyun?wait()(unconditionally block) yaget()(block aur consume) ke unlike,wait_forat most given duration ke liye block karta hai aurfuture_statusreturn karta hai. Yeh value kabhi consume nahi karta, isliye ready hone par baad meinget()abhi bhi allowed hai.future_status::timeoutpar branch karo. Yeh step kyun? 100 ms baad producer (300 ms) done nahi hai, isliye statustimeouthai aur hum give-up branch lete hain — koi crash nahi, koi hang nahi.
Verify: producer 300 ms aur deadline 100 ms ke saath, , isliye
wait_fortimeoutreturn karta hai. (readybranch aurget()==7tabhi fire karte jab deadline 300 ms se zyada hoti.)
Example 8 — Cell G: shared_future ke saath kai readers
Forecast: kaun sa ek conversion ek single-use future ko broadcastable banaata hai, aur kya har thread
get()call kar sakta hai?
std::promise<int> prom;
std::shared_future<int> shared = prom.get_future().share(); // Step 1
auto reader = [shared](int id) {
int v = shared.get(); // Step 3 : har ek theek se read karta hai
std::cout << "reader " << id << " saw " << v << "\n";
};
std::thread a(reader, 1), b(reader, 2), c(reader, 3);
prom.set_value(55); // Step 2
a.join(); b.join(); c.join();.share(). Yeh step kyun?future::share()shared state ko ek std::shared_future mein move karta hai, jo copyable hai aur jiskaget()one-shot nahi hai — yeh har call par ekconst&/copy return karta hai.set_value(55). Yeh step kyun? Ek producer abhi bhi exactly ek baar fulfill karta hai; broadcast reading side par hai.- Teen
get()calls. Yeh step kyun legal hai?shared_futureki teen copies mein se har ekget()call kar sakti hai; woh sab ek hi55observe karti hain. Ek plainfutureke saath, sirf pehla succeed karta aur baakino_statethrow karte.
Verify: teeno readers
55print karte hain; kul teen successfulget()s (plain one-shotfutureke saath impossible).
Example 9 — Cells I + J: real word problem, aur packaged_task twist
Forecast: main konsa final number print karta hai, aur kitne futures chahiye?
auto compute = [](std::promise<int> p, int a, int b) {
p.set_value(a * b);
};
std::promise<int> pr, pp;
auto f_risk = pr.get_future();
auto f_pnl = pp.get_future();
std::thread t1(compute, std::move(pr), 3, 100); // risk = 300
std::thread t2(compute, std::move(pp), 5, 40); // pnl = 200
int total = f_risk.get() + f_pnl.get(); // Step 3
std::cout << total << "\n";
t1.join(); t2.join();- Do promises, do futures. Kyun? Do independent results ⇒ do shared states concurrently chal rahe hain — yeh Cell I ka parallel-fan-out hai.
- Do threads simultaneously compute karte hain. Kyun?
riskaurpnlke beech koi data dependency nahi, isliye woh overlap karte hain. Dekho std::thread ki har ek kaise launch hoti hai. f_risk.get() + f_pnl.get(). Yeh step kyun?mainhar ek par baari baari block karta hai; total time ≈ dono mein se slower ka waqt, unka sum nahi.
Verify: .
Ab exam twist (Cell J) — jab tum std::packaged_task use karte ho to promise kahan hai?
std::packaged_task<int()> task([]{ return 6 * 7; }); // task andar ek promise chhupaata hai
std::future<int> fut = task.get_future(); // task se hi future
std::thread(std::move(task)).detach(); // task run karna = ise fulfill karna
std::cout << fut.get() << "\n"; // -> 42- Explicit
promisekyun nahi? Ekpackaged_taskek internal promise own karta hai. Task ko invoke karna automatically return value ke saathset_valuecall karta hai (ya throw karne parset_exception). Tum sirf future ke saath interact karte ho. std::async se compare karo, jo tumhare liye poora promise/thread/future trio banata hai.
Verify: packaged-task future yield karta hai, Example 1 jaisa bilkul, lekin promise machinery task ke andar hidden hai.
Recall
Recall Kaun sa cell block karne ki jagah throw karta hai, aur kyun?
Cell D (broken promise) ::: Promise ka destructor auto-store karta hai future_error(broken_promise) aur ready mark karta hai, isliye get() deadlock karne ki jagay throw karta hai.
Recall Example 2 ka
get() notify miss kyun nahi hua?
Value-set-first ::: cv.wait(lk, []{return ready;}) sone se pehle predicate check karta hai; kyunki ready pehle se true tha to woh instantly return kar gaya — missed notify irrelevant hai.
Recall Ek one-shot future ko broadcast future mein kaun convert karta hai?
.share() ::: Yeh state ko ek copyable std::shared_future mein move karta hai jiska get() kai baar call ho sakta hai, har reader ke liye ek baar.
Recall Kaun sa call status deta hai value consume kiye bina?
wait_for ::: Given duration ke baad at most future_status::ready / timeout / deferred return karta hai, future ko invalidate kiye bina.