C++ कॉरआउटिंस उदाहरण

C Kora A Utinsa Udaharana



Coroutines एक भाषा सुविधा प्रदान करता है जो आपको एक संरचित और अनुक्रमिक दृष्टिकोण को बढ़ावा देते हुए, अधिक व्यवस्थित और रैखिक फैशन में अतुल्यकालिक कोड लिखने में सक्षम बनाता है। वे पूरे थ्रेड को रोके बिना विशेष उदाहरणों पर किसी फ़ंक्शन के निष्पादन को रोकने और पुनः आरंभ करने के लिए एक तंत्र देते हैं। कोरूटाइन उन कार्यों को संभालने में सहायक होते हैं जिनमें I/O संचालन के लिए प्रतीक्षा करने की आवश्यकता होती है जैसे फ़ाइल से पढ़ना या नेटवर्क कॉल भेजना।

कॉरआउट्स जनरेटर की अवधारणा पर आधारित हैं जहां एक फ़ंक्शन मान उत्पन्न कर सकता है और बाद में निष्पादन जारी रखने के लिए फिर से शुरू किया जा सकता है। Coroutines अतुल्यकालिक संचालन को प्रबंधित करने के लिए एक शक्तिशाली उपकरण प्रदान करता है और आपके कोड की समग्र गुणवत्ता में काफी सुधार कर सकता है।

कोरटाइन्स का उपयोग

आधुनिक प्रोग्रामिंग में, विशेषकर C++ जैसी भाषाओं में, कई कारणों से कोरआउट्स की आवश्यकता होती है। यहां कुछ प्रमुख कारण बताए गए हैं कि क्यों कॉरआउट्स फायदेमंद हैं:







Coroutines अतुल्यकालिक प्रोग्रामिंग के लिए एक सुंदर समाधान प्रदान करता है। वे एक ऐसा कोड बनाना संभव बनाते हैं जो अनुक्रमिक और अवरुद्ध प्रतीत होता है जिसके बारे में तर्क करना और समझना आसान है। कॉरआउटाइन थ्रेड को अवरुद्ध किए बिना विशिष्ट बिंदुओं पर उनके निष्पादन को निलंबित कर सकते हैं, जिससे अन्य कार्यों का समानांतर संचालन संभव हो सकता है। इसके कारण, सिस्टम संसाधनों का अधिक प्रभावी ढंग से उपयोग किया जा सकता है, और उन अनुप्रयोगों में प्रतिक्रियाशीलता बढ़ जाती है जिनमें I/O संचालन या बाहरी घटनाओं की प्रतीक्षा शामिल होती है।



वे कोड को समझना और बनाए रखना आसान बना सकते हैं। जटिल कॉलबैक श्रृंखलाओं या राज्य मशीनों को समाप्त करके, कॉरआउट्स कोड को अधिक रैखिक और अनुक्रमिक शैली में लिखने में सक्षम बनाता है। इससे कोड संगठन में सुधार होता है, नेस्टिंग कम होती है और तर्क को समझना आसान हो जाता है।



कॉरआउट्स समवर्तीता और समानता को संभालने के लिए एक संरचित तरीका प्रदान करते हैं। वे आपको अधिक सहज वाक्यविन्यास का उपयोग करके जटिल समन्वय पैटर्न और अतुल्यकालिक वर्कफ़्लो को व्यक्त करने की अनुमति देते हैं। पारंपरिक थ्रेडिंग मॉडल के विपरीत जहां थ्रेड्स को अवरुद्ध किया जा सकता है, कॉरआउट्स सिस्टम संसाधनों को मुक्त कर सकते हैं और एक कुशल मल्टीटास्किंग सक्षम कर सकते हैं।





आइए C++ में कोरटाइन के कार्यान्वयन को प्रदर्शित करने के लिए कुछ उदाहरण बनाएं।

उदाहरण 1: बुनियादी कोरआउटिंस

बुनियादी कोरआउट्स उदाहरण निम्नलिखित में प्रदान किया गया है:



#शामिल करें

#शामिल करें <कोरआउटिन>

struct दिसकोरआउट {

struct वादा_प्रकार {

ThisCorout get_return_object ( ) { वापस करना { } ; }

कक्षा :: सस्पेंड_कभी नहीं प्रारंभिक_निलंबन ( ) { वापस करना { } ; }

कक्षा :: सस्पेंड_कभी नहीं अंतिम_निलंबन ( ) कोई अपवाद नहीं { वापस करना { } ; }

खालीपन अनियंत्रित अपवाद ( ) { }

खालीपन वापसी_शून्य ( ) { }

} ;

बूल वेट_रेडी ( ) { वापस करना असत्य ; }

खालीपन प्रतीक्षा करें_निलंबित करें ( कक्षा :: coroutine_handle <> एच ) { }

खालीपन प्रतीक्षा_फिर से शुरू करें ( ) { कक्षा :: अदालत << 'कोरटाइन फिर से शुरू हो गया है।' << कक्षा :: अंतः ; }

} ;

दिसकोरआउट फू ( ) {

कक्षा :: अदालत << 'कोरटाइन शुरू हो गया है।' << कक्षा :: अंतः ;

सह_प्रतीक्षा एसटीडी :: सस्पेंड_हमेशा { } ;

सह_वापसी ;

}

int यहाँ मुख्य ( ) {

ऑटो करोड़ = फू ( ) ;

कक्षा :: अदालत << 'कोरटाइन बनाया गया है।' << कक्षा :: अंतः ;

करोड़। प्रतीक्षा_फिर से शुरू करें ( ) ;

कक्षा :: अदालत << 'कोरटाइन समाप्त हो गया।' << कक्षा :: अंतः ;

वापस करना 0 ;

}

आइए पहले दिए गए कोड को देखें और इसे विस्तार से समझाएं:

आवश्यक हेडर फ़ाइलों को शामिल करने के बाद, हम 'दिसकोरआउट' संरचना को परिभाषित करते हैं जो एक कोरआउटिन का प्रतिनिधित्व करता है। 'ThisCorout' के अंदर, एक और संरचना जो 'promise_type' परिभाषित की गई है जो coroutine वादे को संभालती है। यह संरचना विभिन्न कार्य प्रदान करती है जो कोरआउटिन मशीनरी के लिए आवश्यक हैं।

कोष्ठक के अंदर, हम get_return_object() फ़ंक्शन का उपयोग करते हैं। यह कोरआउटिन ऑब्जेक्ट को ही लौटाता है। इस उदाहरण में, यह एक खाली 'ThisCorout' ऑब्जेक्ट लौटाता है। फिर, इनिशियल_सस्पेंड() फ़ंक्शन लागू किया जाता है जो कॉरआउटिन पहली बार शुरू होने पर व्यवहार को निर्धारित करता है। std::suspend_never का अर्थ है कि कोरआउटिन को प्रारंभ में निलंबित नहीं किया जाना चाहिए।

उसके बाद, हमारे पास फाइनल_सस्पेंड() फ़ंक्शन है जो कॉरआउटिन समाप्त होने पर व्यवहार को निर्धारित करता है। std::suspend_never का अर्थ है कि कोरआउटिन को उसके अंतिम रूप देने से पहले निलंबित नहीं किया जाना चाहिए।

यदि कोई कोरआउटिन अपवाद फेंकता है, तो unhandled_exception() विधि लागू की जाती है। इस उदाहरण में, यह एक खाली फ़ंक्शन है, लेकिन आप आवश्यकतानुसार अपवादों को संभाल सकते हैं। जब कोरआउटिन कोई मान दिए बिना समाप्त हो जाता है, तो return_void() विधि लागू हो जाती है। इस मामले में, यह भी एक खाली फ़ंक्शन है।

हम 'दिसकोरआउट' के भीतर तीन सदस्य कार्यों को भी परिभाषित करते हैं। यह जांचने के लिए wait_ready() फ़ंक्शन को कॉल किया जाता है कि कोरआउटिन निष्पादन फिर से शुरू करने के लिए तैयार है या नहीं। इस उदाहरण में, यह हमेशा गलत रिटर्न देता है जो इंगित करता है कि कोरआउटिन तुरंत फिर से शुरू करने के लिए तैयार नहीं है। जब कोरआउटिन निलंबित होने वाला होता है, तो wait_suspend() विधि को कॉल किया जाता है। यहां, यह एक खाली फ़ंक्शन है जिसका अर्थ है कि कोई निलंबन आवश्यक नहीं है। जब निलंबन के बाद कोरआउटिन फिर से शुरू होता है तो प्रोग्राम wait_resume() को कॉल करता है। यह सिर्फ एक संदेश आउटपुट करता है जिसमें कहा गया है कि कोरआउटिन फिर से शुरू कर दिया गया है।

कोड की अगली पंक्तियाँ foo() coroutine फ़ंक्शन को परिभाषित करती हैं। foo() के अंदर, हम एक संदेश प्रिंट करके शुरू करते हैं जिसमें कहा गया है कि कोरआउटिन शुरू हो गया है। फिर, co_await std::suspend_always{} का उपयोग कोरआउटिन को निलंबित करने के लिए किया जाता है और इंगित करता है कि इसे बाद में फिर से शुरू किया जा सकता है। Co_return स्टेटमेंट का उपयोग बिना कोई मूल्य लौटाए कॉरआउटिन को समाप्त करने के लिए किया जाता है।

मुख्य() फ़ंक्शन में, हम foo() को कॉल करके 'ThisCorout' प्रकार का एक ऑब्जेक्ट 'cr' बनाते हैं। यह कॉरआउटिन बनाता और प्रारंभ करता है. फिर, एक संदेश मुद्रित होता है जो बताता है कि कोरआउटिन बनाया गया है। इसके बाद, हम इसके निष्पादन को फिर से शुरू करने के लिए 'सीआर' कॉरआउटिन ऑब्जेक्ट पर wait_resume() को कॉल करते हैं। wait_resume() के अंदर, 'द कॉरआउटिन फिर से शुरू हो गया है' संदेश मुद्रित होता है। अंत में, हम एक संदेश प्रदर्शित करते हैं जिसमें कहा गया है कि कार्यक्रम समाप्त होने से पहले कोरटाइन पूरा हो गया है।

जब आप यह प्रोग्राम चलाते हैं, तो आउटपुट इस प्रकार होता है:

उदाहरण 2: पैरामीटर्स और यील्डिंग के साथ कोरआउटाइन

अब, इस उदाहरण के लिए, हम एक कोड प्रदान करते हैं जो संख्याओं के अनुक्रम का उत्पादन करने के लिए जेनरेटर जैसा व्यवहार बनाने के लिए पैरामीटर और सी++ में कोरआउटिन के उपयोग को प्रदर्शित करता है।

#शामिल करें

#शामिल करें <कोरआउटिन>

#शामिल <वेक्टर>

struct न्यूकोरटाइन {

struct p_प्रकार {

कक्षा :: वेक्टर < int यहाँ > मान ;

NEWCoroutine get_return_object ( ) { वापस करना { } ; }

कक्षा :: सस्पेंड_हमेशा प्रारंभिक_निलंबन ( ) { वापस करना { } ; }

कक्षा :: सस्पेंड_हमेशा अंतिम_निलंबन ( ) कोई अपवाद नहीं { वापस करना { } ; }

खालीपन अनियंत्रित अपवाद ( ) { }

खालीपन वापसी_शून्य ( ) { }

कक्षा :: सस्पेंड_हमेशा उपज_मूल्य ( int यहाँ कीमत ) {

मूल्य. वापस धक्का देना ( कीमत ) ;

वापस करना { } ;

}

} ;

कक्षा :: वेक्टर < int यहाँ > मान ;

struct इटरेटर {

कक्षा :: coroutine_handle <> कोरस_हैंडल ;

बूल ऑपरेटर != ( कॉन्स्ट इटरेटर & अन्य ) कॉन्स्ट { वापस करना कोरस_हैंडल != अन्य। कोरस_हैंडल ; }

इटरेटर & ऑपरेटर ++ ( ) { कोरस_हैंडल. फिर शुरू करना ( ) ; वापस करना * यह ; }

int यहाँ ऑपरेटर * ( ) कॉन्स्ट { वापस करना कोरस_हैंडल. वादा ( ) . मान [ 0 ] ; }

} ;

पुनरावर्तक आरंभ ( ) { वापस करना इटरेटर { कक्षा :: coroutine_handle < p_प्रकार >:: from_promise ( वादा ( ) ) } ; }

पुनरावर्तक अंत ( ) { वापस करना इटरेटर { nullptr } ; }

कक्षा :: coroutine_handle < p_प्रकार > वादा ( ) { वापस करना
कक्षा :: coroutine_handle < p_प्रकार >:: from_promise ( * यह ) ; }

} ;

NEWCoroutine जनरेटनंबर्स ( ) {

सह-उपज 5 ;

सह-उपज 6 ;

सह-उपज 7 ;

}

int यहाँ मुख्य ( ) {

NEWCoroutine एन.सी = जनरेटनंबर्स ( ) ;

के लिए ( int यहाँ कीमत : एनसी ) {

कक्षा :: अदालत << कीमत << ' ' ;

}

कक्षा :: अदालत << कक्षा :: अंतः ;

वापस करना 0 ;

}

पिछले कोड में, NEWCoroutine संरचना एक coroutine-आधारित जनरेटर का प्रतिनिधित्व करती है। इसमें एक नेस्टेड 'p_type' संरचना शामिल है जो कोरआउटिन के लिए वादा प्रकार के रूप में कार्य करती है। P_type संरचना उन कार्यों को परिभाषित करती है जो कोरआउटिन मशीनरी के लिए आवश्यक हैं जैसे get_return_object(), प्रारंभिक_सस्पेंड(), अंतिम_सस्पेंड(), unhandled_exception(), और return_void()। पी_टाइप संरचना में यील्ड_वैल्यू (इंट वैल्यू) फ़ंक्शन भी शामिल है जिसका उपयोग कोरआउटिन से मान प्राप्त करने के लिए किया जाता है। यह दिए गए मान को मान वेक्टर में जोड़ता है।

NEWCoroutine संरचना में std::vector सदस्य चर शामिल है जिसे 'मान' कहा जाता है जो उत्पन्न मूल्यों का प्रतिनिधित्व करता है। NEWCoroutine के अंदर, एक नेस्टेड स्ट्रक्चर इटरेटर है जो जेनरेट किए गए मानों पर पुनरावृति करने की अनुमति देता है। इसमें एक coro_handle है जो coroutine के लिए एक हैंडल है और पुनरावृत्ति के लिए !=, ++, और * जैसे ऑपरेटरों को परिभाषित करता है।

हम p_type वादे से coro_handle प्राप्त करके कोरूटीन की शुरुआत में एक पुनरावर्तक बनाने के लिए begin() फ़ंक्शन का उपयोग करते हैं। जबकि अंत() फ़ंक्शन एक पुनरावर्तक बनाता है जो कोरआउटिन के अंत का प्रतिनिधित्व करता है और एक nullptr coro_handle के साथ निर्मित होता है। उसके बाद, p_type वादे से एक coroutine_handle बनाकर वादा प्रकार को वापस करने के लिए प्रॉमिस() फ़ंक्शन का उपयोग किया जाता है। जेनरेटनंबर्स() फ़ंक्शन एक कोरआउटिन है जो सह_यील्ड कीवर्ड का उपयोग करके तीन मान - 5, 6, और 7 - उत्पन्न करता है।

मुख्य() फ़ंक्शन में, 'nc' नामक NEWCoroutine का एक उदाहरण generateNumbers() coroutine को लागू करके बनाया जाता है। यह कोरआउटिन को आरंभ करता है और उसकी स्थिति को पकड़ लेता है। एक रेंज-आधारित 'फॉर' लूप का उपयोग 'एनसी' के मानों को पुनरावृत्त करने के लिए किया जाता है, और प्रत्येक मान मुद्रित किया जाता है जिसे std::cout का उपयोग करके एक स्थान से अलग किया जाता है।

उत्पन्न आउटपुट इस प्रकार है:

निष्कर्ष

यह आलेख C++ में कोरआउटिंस के उपयोग को प्रदर्शित करता है। हमने दो उदाहरणों पर चर्चा की। पहले उदाहरण के लिए, कोरआउटिन फ़ंक्शंस का उपयोग करके C++ प्रोग्राम में मूल कोरआउटिन बनाया जाता है। जबकि दूसरा प्रदर्शन मापदंडों के साथ कोरआउट्स का उपयोग करके और संख्याओं का अनुक्रम बनाने के लिए जनरेटर जैसा व्यवहार उत्पन्न करने के लिए किया गया था।