संसाधन अधिग्रहण आरंभीकरण
संसाधन अधिग्रहण आरंभीकरण आरएआईआई (RAII)[1] का प्रोग्रामिंग विशिष्ट स्वरूप हैI[2] विशेष भाषा के व्यवहार का वर्णन करने के लिए कई ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग, स्टेटिकली टाइप्ड प्रोग्रामिंग भाषा में उपयोग किया जाता है। आरएआईआई में, संसाधन धारण करना वर्ग अपरिवर्तनीय है, एवं वस्तु जीवनकाल से बना हुआ है। कंस्ट्रक्टर (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) द्वारा ऑब्जेक्ट क्रिएशन (विशेष रूप से इनिशियलाइज़ेशन) के समय संसाधन आवंटन (कंप्यूटर) (या अधिग्रहण) किया जाता है, जबकि डिस्ट्रक्टर (कंप्यूटर) द्वारा वस्तु नष्ट (विशेष रूप से फाइनलाइज़ेशन) के समय रिसोर्स डीलोकेशन (प्रस्तावित) किया जाता है। दूसरे शब्दों में, सफल होने के लिए आरंभीकरण के लिए संसाधन अधिग्रहण सफल होना चाहिए। इस प्रकार संसाधन को आरंभीकरण समाप्त होने एवं अंतिम रूप देने के मध्य आयोजित होने का आश्वासन दिया जाता हैI (संसाधनों को धारण करना वर्ग अपरिवर्तनीय है), एवं वस्तु के जीवित रहने पर ही आयोजित किया जाना है। इस प्रकार, यदि कोई वस्तु लीक नहीं होती है, तो कोई संसाधन लीक नहीं होता है।
आरएआईआई (RAII) सबसे प्रमुख रूप से C ++ के साथ जुड़ा हुआ है जहां इसकी उत्पत्ति हुई, किन्तु D (प्रोग्रामिंग भाषा),[3] एडा (प्रोग्रामिंग भाषा),[4][5] एवं रस्ट (प्रोग्रामिंग भाषा) भी है।[6] C ++ में असामान्यता सुरक्षा संसाधन प्रबंधन (कंप्यूटिंग) के लिए प्रौद्योगिकी विकसित की गई थी[7] 1984-89 के समय, मुख्य रूप से बज़्ने स्ट्रॉस्ट्रुप एवं एंड्रयू कोएनिग (प्रोग्रामर) द्वारा,[8] एवं यह शब्द स्वयं स्ट्रॉस्ट्रुप द्वारा बनाया गया था।[9] आरएआईआई को सामान्यतः प्रारंभिकता के रूप में उच्चारित किया जाता है, कभी-कभी "R, A, डबल I" के रूप में उच्चारित किया जाता है।[10] इस विशिष्ट स्वरूप के अन्य नामों में कंस्ट्रक्टर एक्वायर, डिस्ट्रक्टर प्रस्तावित (CADRe) सम्मिलित हैं।[11] एवं उपयोग की विशेष शैली को स्कोप-आधारित संसाधन प्रबंधन (एसबीआरएम) कहा जाता है।[12] यह शब्द स्वचालित गतिमान की विशेष स्तिथि के लिए है। (RAII) आरएआईआई संसाधनों को आजीवन वस्तु से जोड़ता है, जो सीमा के प्रवेश एवं निकास के साथ मिल नहीं सकता है। (विशेष रूप से मुफ्त स्टोर पर आवंटित चर का जीवनकाल किसी भी सीमा से असंबंधित होता है।) चूँकि, स्वचालित गतिमान (SBRM) के लिए आरएआईआई (RAII) को उपयोग करना सबसे सरल स्थिति हैI
C ++ 11 उदाहरण
निम्न C++11 उदाहरण फ़ाइल एक्सेस एवं म्यूटेक्स लॉकिंग के लिए आरएआईआई (RAII) के उपयोग को प्रदर्शित करता है
/#include <fstream>
#include <fstream> #include <mutex> #include <stdexcept> #include <string> void WriteToFile(const std::string& message) { // |mutex| is to protect access to |file| (which is shared across threads). static std::mutex mutex; // Lock |mutex| before accessing |file|. std::lock_guard<std::mutex> lock(mutex); // Try to open file. std::ofstream file("example.txt"); if (!file.is_open()) { throw std::runtime_error("unable to open file"); } // Write |message| to |file|. file << message << std::endl; // |file| will be closed first when leaving scope (regardless of exception) // |mutex| will be unlocked second (from |lock| destructor) when leaving scope // (regardless of exception). }
यह कोड असामान्यता-सुरक्षित है क्योंकि C ++ आश्वासन देता है कि सभी स्टैक ऑब्जेक्ट संलग्न सीमा के अंत में नष्ट हो जाते हैं, जिसे उद्घट्टन कहा जाता है। लॉक एवं फाइल ऑब्जेक्ट्स दोनों के विनाशकों को प्रोग्राम से प्रत्यागमन पर आह्वान करने का आश्वासन दिया जाता है, फिर कोई दोषकथन हो अथवा न हो।[13]स्थानीय गतिमान कार्य के अंदर कई संसाधनों के सरल प्रबंधन की अनुमति देते हैं: वे अपने निर्माण के विपरीत क्रम में नष्ट हो जाते हैं, एवं वस्तु केवल पूर्ण रूप से निर्मित होने पर ही नष्ट हो जाती है- अर्थात, यदि इसके निर्माता से कोई दोषारोपण नहीं होताहै।[14] आरएआईआई का उपयोग संसाधन प्रबंधन को अधिक सरल करता है, समग्र कोड आकार को अल्पकरता है एवं कार्यक्रम की शुद्धता सुनिश्चित करने में सहायता करता है। आरएआईआई (RAII) इसलिए उद्योग-मानक दिशानिर्देशों द्वारा अनुशंसित है,[15] एवं अधिकांश C ++ मानक पुस्तकालय विशिष्ट स्वरूप का पालन करते हैं।[16]
लाभ
संसाधन प्रबंधन प्रौद्योगिकी के रूप में आरएआईआई (RAII) के लाभ यह हैं कि यह कैप्सूलीकरण, असामान्यता सुरक्षा (स्टैक संसाधनों के लिए), एवं स्थानीयता प्रदान करता है (यह अधिग्रहण एवं मुक्त करना, तर्क को साथ में लिखने की अनुमति देता है)।
कैप्सूलीकरण प्रदान किया जाता है क्योंकि संसाधन प्रबंधन तर्क को कक्षा में परिभाषित किया जाता है, प्रत्येक आह्वान साइट पर नहीं किया जाता है। स्टैक संसाधनों के लिए असामान्यता सुरक्षा प्रदान की जाती है (संसाधन जो उसी सीमा में निरंतर किए जाते हैं जैसे वे अधिग्रहित होते हैं) संसाधन को स्टैक चर(किसी दिए गए सीमा में घोषित स्थानीय गतिमान) के जीवनकाल में रखकर: यदि कोई असामान्यता हैंडलिंग विस्थापित कर दी जाती है, एवं उचित असामान्यता हैंडलिंग उपस्तिथ है, वर्तमान स्कोप (कंप्यूटर साइंस) से बाहर निकलने पर निष्पादित किया जाने वाला मात्र कोड उस सीमा में घोषित वस्तुओं के विनाशक हैं। अंत में, परिभाषा का स्थान वर्ग परिभाषा में साथ में कंस्ट्रक्टर एवं डिस्ट्रक्टर परिभाषाओं को लिखकर प्रदान किया जाता है।
इसलिए संसाधन प्रबंधन को स्वत: आवंटन एवं सुधार प्राप्त करने के लिए उपयुक्त वस्तुओं के जीवनकाल से जुड़ा होना चाहिए। आरंभीकरण के समय संसाधनों का अधिग्रहण किया जाता है, जब उनके उपलब्ध होने से पूर्व उपयोग किए जाने का कोई संयोग नहीं होता है, एवं उन्हीं वस्तुओं के विनाश के साथ निरंतर किया जाता है।
आरएआईआई की तुलना finally
जावा में प्रयुक्त निर्माण, स्ट्रॉस्ट्रुप ने लिखा है कि "यथार्थवादी प्रणालियों में, संसाधनों के प्रकारों की तुलना में कहीं अधिक संसाधन अधिग्रहण होते हैं, इसलिए 'संसाधन अधिग्रहण आरंभीकरण है ' प्रौद्योगिकी 'अंततः' निर्माण के उपयोग की तुलना में अर्घ्य कोड की ओर ले जाती है।"[1]
विशिष्ट उपयोग
आरएआईआई (RAII) डिज़ाइन का उपयोग प्रायः थ्रेड (कंप्यूटिंग) मल्टी-थ्रेडेड अनुप्रयोगों में म्यूटेक्स लॉक को नियंत्रित करने के लिए किया जाता है। उस उपयोग में, वस्तु नष्ट होने पर लॉक को प्रस्तावित करता है। इस परिदृश्य में आरएआईआई (RAII) के बिना गतिरोध की संभावना अधिक होगी एवं म्यूटेक्स को लॉक करने की युक्ति इसे अनलॉक करने की युक्ति से अधिक दूर होगी। आरएआईआई के साथ, म्यूटेक्स को लॉक करने वाले कोड में अनिवार्य रूप से अनुभूति सम्मिलित है कि निष्पादन आरएआईआई ऑब्जेक्ट के सीमा को त्यागने पर लॉक निरंतर किया जाएगा।
अन्य विशिष्ट उदाहरण फाइलों के साथ वार्तालाप कर रहा है: हमारे पास वस्तु हो सकती है जो फ़ाइल का प्रतिनिधित्व करती है जो लिखने के लिए प्रकट हुई है, जिसमें फ़ाइल को कंस्ट्रक्टर में विकसित किया जाता है एवं जब निष्पादन वस्तु सीमा को त्याग देता है तो समाप्त हो जाता है। दोनों ही स्तिथियों में, आरएआईआई केवल यह सुनिश्चित करता है कि विचाराधीन संसाधन उचित रूप से निरंतर किया जाए; असामान्यता सुरक्षा बनाए रखने के लिए प्रबंध किया जाना चाहिए। यदि डेटा संरचना या फ़ाइल को संशोधित करने वाला कोड असामान्यता-सुरक्षित नहीं है, तो म्यूटेक्स को अनलॉक किया जा सकता है या फ़ाइल को डेटा संरचना के साथ समाप्त किया जा सकता है या फ़ाइल दूषित हो सकती है।
गतिशील रूप से आवंटित वस्तुओं का स्वामित्व (आवंटित स्मृति new
C ++ में) को आरएआईआई के साथ भी नियंत्रित किया जा सकता है, जैसे कि आरएआईआई (स्टैक-आधारित) वस्तु नष्ट होने पर वस्तु निरंतर किया जाता है। इस प्रयोजन के लिए, C++11 मानक पुस्तकालय स्मार्ट सूचक वर्गों को परिभाषित करता है std::unique_ptr
स्वामित्व वाली वस्तुओं के लिए एवं std::shared_ptr
स्वामित्व वाली वस्तुओं के लिए इस प्रकार की कक्षाएं भी उपलब्ध हैं std::auto_ptr
C ++ 98 में, एवं boost::shared_ptr के माध्यम से
बूस्ट (C ++ पुस्तकालय) में भी उपलब्ध हैं।
कंपाइलर क्लीनअप एक्सटेंशन
क्लैंग एवं जीएनयू कंपाइलर संग्रह दोनों आरएआईआई का समर्थन करने के लिए C (प्रोग्रामिंग भाषा) भाषा के लिए अन्य-मानक एक्सटेंशन प्रारम्भ करते हैं: क्लीनअप चर विशेषता [17] निम्नलिखित दिए गए विनाशक प्रोग्राम के साथ चर को एनोटेट करता है जिसे चर सीमा से बाहर होने पर आह्वान करेगा:
void example_usage() { __attribute__((cleanup(fclosep))) FILE *logfile = fopen("logfile.txt", "w+");
fputs("hello logfile!", logfile); }
इस उदाहरण में, कंपाइलर fclosep प्रोग्राम को उदाहरण_उपयोग रिटर्न से पहले लॉगफ़ाइल पर कॉल करने की व्यवस्था करता है।
सीमाएं
आरएआईआई केवल स्टैक-आवंटित वस्तुओं द्वारा अधिग्रहित एवं निरंतर (प्रत्यक्ष या अप्रत्यक्ष रूप से) संसाधनों के लिए कार्य करता है, जहां उत्तम रूप से परिभाषित स्थिर वस्तु जीवनकाल है। हीप-आबंटित वस्तुएँ जो स्वयं संसाधनों को प्राप्त एवं निरंतर करती हैं, C++ सहित कई भाषाओं में सरल हैं। आरएआईआई अपने संसाधन-विमोचन विनाशक (या समतुल्य) को ट्रिगर करने के लिए समूह-आधारित वस्तुओं पर निर्भर करता है जिससे सभी संभावित निष्पादन मार्गो के साथ स्पष्ट रूप से विस्थापित किया जा सके।[18] चक्रीय रूप से संदर्भित वस्तुओं के लिए शक्तिहीन पॉइंटर्स के साथ, सभी हीप वस्तुओं को प्रबंधित करने के लिए स्मार्ट पॉइंटर्स का उपयोग करके इसे प्राप्त किया जा सकता है।
C ++ में, स्टैक अनइंडिंग केवल तभी होने का आश्वासन देता है जब असामान्यता कहीं मिल जाता है। ऐसा इसलिए है क्योंकि यदि किसी प्रोग्राम में कोई मिलान करने वाला हैंडलर नहीं मिलता है, तो प्रोग्राम टर्मिनेट () कहा जाता है; इस आह्वान को समाप्त करने से पूर्व स्टैक अवांछित है या नहीं () कार्यान्वयन-परिभाषित (15.5.1) है। (C++03 मानक, §15.3/9)।[19] यह व्यवहार सामान्यतः स्वीकार्य है, क्योंकि ऑपरेटिंग प्रणाली प्रोग्राम समाप्ति पर शेष संसाधन जैसे स्मृति, फ़ाइलें, सॉकेट इत्यादि निरंतर करता है।
संदर्भ गिनती
पर्ल, पायथन (प्रोग्रामिंग भाषा) (सीपीथॉन कार्यान्वयन में),[20] एवं पीएचपी[21] संदर्भ गणना द्वारा वस्तु जीवनकाल का प्रबंधन करें, जिससे आरएआईआई (RAII) का उपयोग करना संभव हो जाता है। जिन वस्तुओं को अब संदर्भित नहीं किया जाता है उन्हें तुरंत नष्ट कर दिया जाता है या अंतिम रूप दिया जाता है एवं निरंतर किया जाता है, इसलिए विध्वंसक या फ़िनलिज़र (finalizer) उस समय संसाधन निरंतर कर सकता है। चूँकि, यह सदैव ऐसी भाषाओं में प्रयुक्तता नहीं होता है, एवं विशेष रूप से पायथन में निराश होता है (संदर्भ प्रबंधको की ओर में एवं शक्तिहीन पैकेज से अंतिम रूप देने वालों के ओर में)। चूँकि, वस्तु जीवन काल अनिवार्य रूप से किसी भी सीमा से बंधे नहीं हैं, एवं वस्तुओं को अन्य-नियतात्मक रूप से नष्ट किया जा सकता है या नहीं। यह अशुद्धि से उन संसाधनों को लीक करना संभव बनाता है जिन्हें किसी सीमा के अंत में निरंतर किया जाना चाहिए था। स्थिर गतिमान (विशेष रूप से वैश्विक गतिमान) में संग्रहीत वस्तुओं को कार्यक्रम के समाप्त होने पर अंतिम रूप नहीं दिया जा सकता है, इसलिए उनके संसाधन निरंतर नहीं किए जाते हैं; उदाहरण के लिए, सी पायथन ऐसी वस्तुओं को अंतिम रूप देने का कोई आश्वासन नहीं देता है। इसके अतिरिक्त, परिपत्र संदर्भ वाली वस्तुएं साधारण संदर्भ पटल द्वारा एकत्र नहीं की जाएंगी, एवं अनिश्चित रूप से अधिक समय तक जीवित रहेंगी; अर्थात एकत्र किया गया हो (अधिक परिष्कृत संग्रह द्वारा), विनाश का समय एवं विनाश का क्रम अन्य-नियतात्मक होगा। सी पायथन (CPython) में साइकिल डिटेक्टर है जो चक्रों को ज्ञात करता है एवं चक्र में वस्तुओं को अंतिम रूप देता है, चूँकि सी पायथन (CPython) 3.4 से पूर्व, चक्रों को एकत्र नहीं किया जाता है यदि चक्र में किसी भी वस्तु को अंतिम रूप दिया जाता है।[22]
संदर्भ
- ↑ 1.0 1.1 Stroustrup, Bjarne (2017-09-30). "Why doesn't C++ provide a "finally" construct?". Retrieved 2019-03-09.
- ↑ Sutter, Herb; Alexandrescu, Andrei (2005). C++ Coding Standards. C++ In-Depth Series. Addison-Wesley. p. 24. ISBN 978-0-321-11358-0.
- ↑ "Scope guards". Dlang Tour. Retrieved 21 May 2021.
- ↑ "Gem #70: The Scope Locks Idiom". AdaCore (in English). Retrieved 21 May 2021.
- ↑ The Valadate Project. "Destruction". The Vala Tutorial version 0.30. Retrieved 21 May 2021.
- ↑ "RAII - Rust By Example". doc.rust-lang.org. Retrieved 2020-11-22.
- ↑ Stroustrup 1994, 16.5 Resource Management, pp. 388–89.
- ↑ Stroustrup 1994, 16.1 Exception Handling: Introduction, pp. 383–84.
- ↑ Stroustrup 1994, p. 389. I called this technique "resource acquisition is initialization."
- ↑ Michael Burr (2008-09-19). "How do you pronounce RAII?". Stack Overflow. Retrieved 2019-03-09.
- ↑ Arthur Tchaikovsky (2012-11-06). "Change official RAII to CADRe". ISO C++ Standard - Future Proposals. Google Groups. Retrieved 2019-03-09.
- ↑ Chou, Allen (2014-10-01). "Scope-Based Resource Management (RAII)". Retrieved 2019-03-09.
- ↑ "How can I handle a destructor that fails?". Standard C++ Foundation. Retrieved 2019-03-09.
- ↑ Richard Smith (2017-03-21). "Working Draft, Standard for ProgrammingLanguage C++" (PDF). Retrieved 2019-03-09.
- ↑ Stroustrup, Bjarne; Sutter, Herb (2020-08-03). "C++ Core Guidelines". Retrieved 2020-08-15.
- ↑ "I have too many try blocks; what can I do about it?". Standard C++ Foundation. Retrieved 2019-03-09.
- ↑ "Specifying Attributes of Variables". Using the GNU Compiler Collection (GCC). GNU Project. Retrieved 2019-03-09.
- ↑ Weimer, Westley; Necula, George C. (2008). "Exceptional Situations and Program Reliability" (PDF). ACM Transactions on Programming Languages and Systems. Vol. 30, no. 2.
- ↑ ildjarn (2011-04-05). "RAII and Stack unwinding". Stack Overflow. Retrieved 2019-03-09.
- ↑ "Extending Python with C or C++: Reference Counts". Extending and Embedding the Python Interpreter. Python Software Foundation. Retrieved 2019-03-09.
- ↑ hobbs (2011-02-08). "Does PHP support the RAII pattern? How?". Retrieved 2019-03-09.
- ↑ "gc — Garbage Collector interface". The Python Standard Library. Python Software Foundation. Retrieved 2019-03-09.
अग्रिम पठन
- Stroustrup, Bjarne (1994). The Design and Evolution of C++. Addison-Wesley. Bibcode:1994dec..book.....S. ISBN 978-0-201-54330-8.
बाहरी संबंध
- Sample Chapter: "Gotcha #67: Failure to Employ Resource Acquisition Is Initialization" by Stephen C. Dewhurst
- Interview: "A Conversation with Bjarne Stroustrup" by Bill Venners
- Article: "The Law of The Big Two" by Bjorn Karlsson and Matthew Wilson
- Article: "Implementing the 'Resource Acquisition is Initialization' Idiom" by Danny Kalev
- Article: "RAII, Dynamic Objects, and Factories in C++" by Roland Pibinger
- RAII in Delphi: "One-liner RAII in Delphi" by Barry Kelly