Parent note padhne se pehle, tumhe us par tike har word ka maalik banana hoga. Yeh page har ek ko zero se build karta hai — pehle simple words, phir ek picture, phir kyun topic ko uski zaroorat hai. Upar se neeche padho; har item agले ke liye ek brick hai. Upar bataaye gaye do named ends abhi sirf labels hain; sections 3–6 box ke andar ki machinery build karte hain, aur section 7 ends ko precisely define karta hai.
Do runners ko parallel tracks par imagine karo. Wo saath shuru karte hain, apni apni pace se daudte hain, aur koi doosre ka wait nahi karta jab tak tum unhe batao nahi.
Figure 1 — do arrows do threads hain (teal = main, orange = worker); plum dots mark karte hain ki dono ek hi moment par shuru hote hain aur phir apne apne track par independently aage badhte hain.
Topic ko yeh kyun chahiye: promise/future exist sirf isliye karta hai kyunki ek se zyada thread run ho raha hai. Agar ek thread hota, tum sirf ek function call karte aur uska return value padhte — koi mailbox ki zaroorat nahi. std::thread dekho.
Ek talking stick imagine karo: sirf woh insaan jo ise hold karta hai bol sakta hai; baki sab wait karte hain.
std::mutex m; // the lock object itselfint shared_value; // the thing we protect{ std::lock_guard<std::mutex> lk(m); // lock m here (lk "guards" m) shared_value = 42; // safe: we hold the stick} // lk destroyed -> unlock automatically
Topic ko yeh kyun chahiye: shared state ka flag aur value ek thread dwara write kiya jaata hai aur doosre dwara padha jaata hai — ek mutex un touches ko serialise karta hai taaki koi data race na ho, aur unique_lock exactly woh tool hai jo waiting step ko chahiye. std::mutex and lock_guard dekho.
Ek mailbox ko ek choti red flag ke saath imagine karo: postman ise uthata hai jab letter andar hota hai, taaki tum jaano bahar jaake collect karo.
Topic ko yeh kyun chahiye: iske bina, waiter ek empty box aur ek box mein legitimately-zero value ke beech farq nahi bata sakta. Flag "data present" bit hai — aur yeh woh condition hai jis par agla tool (condition variable) wait karta hai.
Kisi ko note ke saath so hue imagine karo: "mujhe tab jagao jab kettle boil ho." Wo wait karte hue koi energy burn nahi karte; jo kettle boil karta hai woh unke kandhe ko tap karta hai — woh tap notify_one hai.
Figure 2 — teal box sleeping waiter hai jo ek unique_lock hold kar raha hai; orange box setter hai jo abhi value store kar chuka hai aur ready flip kar chuka hai; plum arrow woh notify_one() call hai jo waiter ko jagaata hai. Upar ke busy-wait note se compare karo: woh teal box ko 100% CPU par spin karta instead of soye rehne dene ke.
Alternative — ek busy-wait loop while(!ready) {} (section 4 ke ready flag ka use karke) — CPU ko 100% par kuch nahi karte hue spin karta hai. Condition variable efficient sleep hai.
Yahan canonical wait loop hai jo setter aur waiter perform karte hain, shared state se m, ready, aur cv ka use karke:
std::mutex m;std::condition_variable cv;bool ready = false;int value;// --- SETTER (producer thread) ---{ std::lock_guard<std::mutex> lk(m); // 1. lock the mutex value = 42; // 2. store the value ready = true; // 3. flip the ready flag} // 4. unlock (lk destroyed)cv.notify_one(); // 5. wake the waiter (outside the lock)// --- WAITER (consumer thread) ---{ std::unique_lock<std::mutex> lk(m); // unique_lock, NOT lock_guard cv.wait(lk, []{ return ready; }); // sleeps; releases m while asleep, // re-checks ready on every wake int got = value; // safe: we hold m and ready==true}
Ek physical mailbox ko do keys ke saath imagine karo — writer ki key aur reader ki key — lekin sirf ek box.
Figure 3 — central boxed block shared state hai; andar sections 3–5 ke chaar members hain (value-or-exception, ready flag, mutex, condition variable). Orange arrow promise hai andar likhte hue; teal arrow future hai bahar padhte hue. Dono arrows same box ki taraf point karte hain — yahi "shared" ka matlab hai.
Topic ko yeh kyun chahiye: yeh literally woh "ek cheez hai jise wo milke manage karte hain" hai jo parent note name karta hai. Promise = writing end, future = reading end, shared state = unke beech ka box.
Mailbox ko phir se imagine karo: promise woh slot hai street par jahan postman letter daalta hai; future woh choti door hai tumhari wall ki side par jahan tum ise collect karte ho.
Figure 4 — top row: ek promise ko copy karna (dashed clone, red mein struck through) do writing ends bana deta jo same box ko aim karte, isliye do threads dono set_value call kar sakte — language ise forbid karta hai. Bottom row: std::move single shared state ko purane promise (ab empty, dotted outline) se naye mein (solid) transfer karta hai — abhi bhi exactly ek owner. Picture yahi rule hai: ek box, ek writer.
Topic ko yeh kyun chahiye: std::thread t(worker, std::move(prom)); — tum promise worker ko hand karte ho; ise clone karna woh error hoga jo language allow karne se refuse karta hai. Move semantics and std::move dekho.
Ek sealed envelope kholne ko imagine karo: ek baar kholne aur letter nikalne ke baad, dobara kholne ke liye kuch nahi bacha. Ek doosra get()future_error throw karta hai code no_state ke saath.
Topic ko yeh kyun chahiye: yeh explain karta hai kyun get() future ko invalidate karta hai, kyun valid()false ho jaata hai, aur kyun multiple readers ko std::shared_future chahiye.
Jab yeh foundations solid ho jayein, parent topic bahar higher-level tools se connect hota hai jo same machinery wrap karte hain: std::async and std::launch (jo tumhe automatically future deta hai), std::packaged_task (jo ek callable ke return ko ek promise mein wrap karta hai), aur std::shared_future (ek result ke kai readers).
Khud ko test karo — parent note padhne se pehle tum in mein se har ek answer de sakna chahiye.
Thread kya hai, ek line mein?
Instructions ka ek independent stream jo doosron ke saath ek saath run karta hai.
Data race kya hai aur yeh dangerous kyun hai?
Do threads same memory ko touch karte hain jisme kam se kam ek write kar raha hota hai — yeh undefined behaviour hai (garbage, crash, ya hidden bugs).
Mutex kya guarantee karta hai?
Ek baar mein sirf ek thread protected region mein enter karta hai; doosre wait karte hain, isliye shared access serialised aur safe hoti hai.
lock_guard tumhare liye kya karta hai?
Creation par mutex lock karta hai aur scope ke end par automatically unlock karta hai, taaki tum release karna kabhi na bhulo.
Condition_variable::wait ko lock_guard ki jagah unique_lock kyun chahiye?
Kyunki wait ko sleep karte waqt mutex release karna hota hai aur wake hone par re-acquire karna hota hai, jo sirf unique_lock allow karta hai; lock_guard beech mein unlock nahi kar sakta aur wahan compile nahi hoga.
Ready flag kya kaam karta hai?
Yeh record karta hai ki value box mein rakhi gayi hai ya nahi, taaki reader ek empty box aur ek filled mein fark kar sake.
notify_one aur notify_all kya hain?
Condition-variable calls jo ek waiting thread (notify_one) ya har waiting thread (notify_all) ko wake karte hain jab condition change ho.
Setter ko kis order mein kaam karna chahiye, aur notify kahan jaata hai?
Mutex lock karo, value store karo, ready flag flip karo, unlock karo, phir lock ke bahar notify_one call karo (lock hold karte hue notify karne se woken thread wapas block ho jaata hai).
Ek condition-variable wait ko apni condition loop mein kyun re-check karni chahiye?
Kyunki spurious wakeups (bina notify ke jaagna) hote hain aur woh case bhi hai jahan value wait shuru hone se pehle set ho gayi thi — wait(lk, pred) exactly woh re-checking loop hai.
Handoff actually safe kyun hai (memory-ordering)?
Mutex unlock karna happens-before us same mutex ka agla lock, isliye unlock se pehle ki gayi saari writes (value aur ready) waiter ke wait ke andar re-lock karne ke baad visible hoti hain.
Busy-wait loop ki jagah condition variable kyun use karein?
Yeh waiting thread ko zero CPU cost par so jaane deta hai jab tak signal nahi milta, spin karne ki jagah.
Shared state kya hai?
Ek heap-allocated control block jo value-or-exception, ready flag, mutex, aur condition variable hold karta hai, promise aur future ke beech shared.
std::promise aur std::future kya hain?
Promise writing end hai (set_value ya set_exception ek baar); future reading end hai (get() block karta hai phir ek baar padhta hai).
std::future_error kya hai?
Exception type ( se, logic_error se derived) jo future misuse par throw hoti hai; yeh ek future_errc code carry karta hai jaise broken_promise, future_already_retrieved, ya no_state.
Agar promise bina set kiye destroy ho jaaye toh kya hota hai?
Future ka get() ek std::future_error throw karta hai code broken_promise ke saath.
Exception thread boundary kaise cross karta hai?
Ise std::exception_ptr ke roop mein current_exception() se capture karo, store karo, phir doosre thread mein rethrow_exception se throw karo.
std::promise move-only kyun hai?
Ek shared state mein exactly ek writer hona chahiye; copying ek box ke liye do writing ends bana deta.
Yahan one-shot ka kya matlab hai?
Promise ek baar set hota hai aur future ek baar padha jaata hai; get() value bahar move karta hai aur future ko invalidate karta hai.
std::future ki jagah std::shared_future kab use karoge?
Jab kai threads sab ek hi result padhna chahte hain, kyunki shared_future copyable hai aur uska get() kai baar call kiya ja sakta hai.