समस्या और संदर्भ
यह प्रश्न C++26 std::execution में कोर ऑब्जेक्ट मॉडल का परीक्षण करता है। एक न्यूनतम एसिंक्रोनस ऑपरेशन से शुरुआत करें और एक sender के lazy विवरण, एक receiver के completion अनुबंध, connect द्वारा उत्पन्न operation state, और उस बिंदु को समझाइए जहां start गणना शुरू करता है।
साक्षात्कारकर्ता क्या मूल्यांकन करता है
मुख्य अंतर एक lazy sender विवरण और कनेक्शन के बाद बनाए गए operation state के बीच है: connect स्टेट बनाता है, जबकि start कार्य शुरू करता है। समझाइए कि set_value, set_error, और set_stopped पाइपलाइन के माध्यम से कैसे आगे बढ़ते हैं, क्या scheduler परिवर्तन थ्रेड एफिनिटी को प्रभावित करते हैं, और कैंसलेशन नए साइड इफेक्ट्स को कैसे रोकता है।
पहले पूछे जाने वाले स्पष्टीकरण प्रश्न
कार्य और बैकप्रेशर (Backpressure)
बैच के आकार, अनुमत समवर्तीता (concurrency), इनपुट क्रम, और विफल राइट्स (writes) के लिए पुनः प्रयास (retry) नीति के बारे में पूछें। उत्तर यह निर्धारित करते हैं कि sender कंकरेंसी को सीमित करना है या कतार को सीमित करना है।
शेड्यूलिंग और स्टॉप स्रोत (Stop sources)
पूछें कि I/O और CPU schedulers कैसे प्रदर्शित होते हैं, क्या स्टॉप टाइमआउट से आता है या उपयोगकर्ता की कार्रवाई से, और पहले से सबमिट किए गए सिस्टम कॉल को कैसे पूरा किया जाता है। स्टॉप अनुरोध थ्रेड की जबरन समाप्ति नहीं है।
संसाधन और कमिट सिमेंटिक्स (Commit semantics)
फ़ाइल हैंडल, बफ़र्स और अस्थायी फ़ाइलों के स्वामित्व को स्पष्ट करें, क्या राइट्स इडेम्पोटेंट (idempotent) हैं, और क्या आंशिक बैच रोलबैक हो सकते हैं। यह set_error के बाद की सफाई (cleanup) को परिभाषित करता है।
30-सेकंड का उत्तर ढांचा
"मैं रीड, पार्स और राइट का वर्णन sender adaptors के साथ करता हूँ, फिर निष्पादन संदर्भों (execution contexts) को स्थानांतरित करने के लिए scheduler adaptors का उपयोग करता हूँ। पाइपलाइन lazy बनी रहती है: connect एक operation state बनाता है और start इसे शुरू करता है। प्रत्येक चरण सफलता के मान आगे भेजता है, seterror के माध्यम से त्रुटियाँ, और setstopped के माध्यम से कैंसलेशन भेजता है; एक stop token प्रत्येक चरण तक पहुँचता है। स्टॉप पाथ साइड इफेक्ट्स से पहले जाँच करता है, जबकि ओनर्स सबमिट किए गए I/O को समाप्त और बंद करते हैं तथा अस्थायी फ़ाइलों को साफ़ करते हैं।"
विस्तृत समाधान चरण
चरण 1: वैल्यू और एरर सीमाओं को परिभाषित करें
प्रत्येक चरण के लिए इनपुट और आउटपुट प्रकार परिभाषित करें और पुनर्प्राप्त करने योग्य विफलताओं को स्पष्ट एरर senders में बदलें। अपवादों (exceptions) को scheduler सीमाओं को पार न करने दें; अंतिम receiver को सफलता, विफलता या स्टॉप रिकॉर्ड करने दें।
चरण 2: एक lazy पाइपलाइन की रचना करें
रीडिंग, पार्सिंग और राइटिंग को जोड़ने के लिए let_value, then, या समकक्ष adaptors का उपयोग करें। संयोजन बिना थ्रेड आवंटित किए या I/O निष्पादित किए एक विवरण बनाता है; operation state किसी भी ऐसे साझा स्टेट का स्वामी होता है जिसे कॉलबैक से अधिक समय तक जीवित रहना चाहिए।
चरण 3: Connect और start करें
एक operation state प्राप्त करने के लिए connect(sender, receiver) को कॉल करें, इसे एक लाइव स्कोप में रखें, फिर start को कॉल करें। receiver को operation state से अधिक समय तक जीवित रहना चाहिए; एसिंक्रोनस कॉलबैक नष्ट हो चुकी स्टैक वस्तुओं को संदर्भित नहीं कर सकते हैं।
चरण 4: निष्पादन संदर्भों के बीच ले जाएं
I/O पूरा होने के बाद, पार्सिंग को CPU पूल में ले जाने के लिए एक scheduler sender का उपयोग करें, फिर राइटिंग को एक बाउंडेड I/O पूल में लौटाएं। कतार की क्षमता और निष्पक्षता रिकॉर्ड करें; ब्लॉकिंग राइट्स को एक अनबाउंडेड सामान्य पूल में न रखें।
चरण 5: स्टॉप और बैकप्रेशर का प्रसार करें
प्रत्येक इंटरप्ट करने योग्य चरण में एक stop token पास करें। स्टॉप के बाद, नए बैचों को कतार में न डालें; इसके API के अनुसार इन-फ़्लाइट सिस्टम कॉल को रद्द करें या समाप्त करें। जब कतार भरी होती है, तो एक थ्रॉटलिंग sender मेमोरी को सीमित करने के लिए अपस्ट्रीम कार्य को रोकता है।
चरण 6: त्रुटियों और आंशिक साइड इफेक्ट्स को संभालें
परमाणु रूप से कमिट करने से पहले एक अस्थायी फ़ाइल में लिखें या एक बैच अनुक्रम रिकॉर्ड करें। set_error डाउनस्ट्रीम क्लीनअप और हैंडल बंद करने को ट्रिगर करता है। पुनः प्रयासों के लिए सीमाओं और एक idempotency key की आवश्यकता होती है ताकि वे राइट्स की नकल न कर सकें।
चरण 7: कंकरेंसी और लाइफटाइम सत्यापित करें
एकाधिक schedulers, स्टॉप रेस, पार्स विफलताओं, शॉर्ट राइट्स, और प्रारंभिक receiver विनाश का परीक्षण करें। रेस के लिए थ्रेड विश्लेषक का उपयोग करें और कतार समय, थ्रूपुट, स्टॉप लेटेंसी, और अनरिलीज़्ड operation states को मापें।
उच्च गुणवत्ता वाला नमूना उत्तर
रीड sender बैचों का उत्सर्जन करता है, पार्स sender एक CPU scheduler पर चलता है, और राइट sender एक बाउंडेड I/O scheduler पर चलता है। पाइपलाइन केवल निर्भरताओं का वर्णन करती है; connect operation state बनाता है और start इसे लॉन्च करता है। प्रत्येक चरण value, error, और stopped पूर्णता को संभालता है और एक stop token साझा करता है। रोकना नए बैचों को ब्लॉक करता है, सबमिट किए गए I/O को सुरक्षित रूप से बंद होने देता है, और इडेम्पोटेंट पुनः प्रयासों के लिए अस्थायी फ़ाइलों और बैच आईडी का उपयोग करता है। परीक्षण scheduler हॉप्स, बैकप्रेशर, स्टॉप रेस, और receiver लाइफटाइम को कवर करते हैं।
सामान्य गलतियाँ
- गलती: यह मान लेना कि निर्मित sender पहले से चल रहा है। → कारण: sender lazy होता है। → सुधार: connect/start सीमा का उल्लेख करें।
- गलती: अपवादों को संभालना लेकिन stopped पूर्णता को नहीं। → कारण: स्टॉप एक अलग completion चैनल है। → सुधार: seterror और setstopped दोनों को लागू करें।
- गलती: कैंसलेशन पर थ्रेड को किल करना। → कारण: इसके पास फ़ाइल हैंडल या आंशिक राइट का स्वामित्व हो सकता है। → सुधार: एक stop token का प्रसार करें और सुरक्षित रूप से अनवाइंड करें।
- गलती: बिना किसी सीमा के बैचों को कतारबद्ध करना। → कारण: बैकप्रेशर की कमी से मेमोरी समाप्त हो सकती है। → सुधार: कंकरेंसी, कतार क्षमता, और पुनः प्रयासों को सीमित करें।
फॉलो-अप प्रश्न और उत्तर
फॉलो-अप 1: सीधे futures का उपयोग क्यों नहीं करते?
Sender/receiver शेड्यूलिंग, कैंसलेशन, और तीन completion चैनलों को कंपोज़ेबल बनाता है और कनेक्शन-समय लाइफटाइम नियंत्रण देता है। Futures को आमतौर पर स्टॉप और एरर प्रसार के लिए अतिरिक्त सम्मेलनों की आवश्यकता होती है।
फॉलो-अप 2: क्या start के बाद sender को नष्ट किया जा सकता है?
अस्थायी sender विवरण नष्ट हो सकता है, लेकिन operation state, receiver, और कैप्चर किए गए संसाधन पूर्णता तक मान्य रहने चाहिए। एक टास्क ऑब्जेक्ट या स्कोप को उनका स्वामी होना चाहिए।
फॉलो-अप 3: क्या set_stopped प्रत्येक साइड इफेक्ट को वापस रोल करता है?
नहीं। यह stopped पूर्णता की रिपोर्ट करता है; सबमिट किया गया I/O वापस रोल नहीं हो सकता है। निरंतरता के लिए अस्थायी फ़ाइलों, इडेम्पोटेंट कमिट्स, या क्षतिपूर्ति की आवश्यकता होती है।
फॉलो-अप 4: आप कैसे साबित करते हैं कि राइट्स डुप्लिकेट नहीं हैं?
एक स्थिर बैच आईडी असाइन करें, लिखने से पहले कमिट की गई आईडी की जांच करें, और पुनः प्रयासों को केवल अनुपलब्ध आईडी लिखने दें। विफलताओं, पुनरारंभ, और स्टॉप रेस को इंजेक्ट करें, फिर अंतिम फ़ाइल के साथ कमिट लॉग की तुलना करें।