2010-01-19 15 views
7

क्या संसाधन अधिग्रहण को लागू करने के लिए वैसे भी योजना में प्रारंभ है?आरएआईआई?

मुझे पता है कि आरएआईआई जीसी-एड भाषाओं में अच्छी तरह से काम नहीं करता है (क्योंकि हमें पता नहीं है कि ऑब्जेक्ट नष्ट हो गया है)। हालांकि, योजना में निरंतरता, गतिशील हवा और बंद होने जैसी अच्छी चीजें हैं - क्या आरएआईआई को लागू करने के लिए इसका कुछ संयोजन उपयोग करने का कोई तरीका है?

यदि नहीं, तो योजनाकार RAII का उपयोग न करने के लिए अपने कोड को कैसे डिज़ाइन करते हैं?

[एक सामान्य उदाहरण मैं में चलाने निम्नलिखित है:

मैं एक 3 डी जाल है, मैं एक वर्टेक्स बफर वस्तु इसे करने के लिए atached है, जब मेष नहीं रह गया है प्रयोग किया जाता है, मैं VBO को मुक्त कर दिया चाहते हैं ।]

धन्यवाद!

+0

हाय, एनोन। मैं सोच रहा हूं कि क्या मेरा जवाब आपको संतुष्ट करता है, या यदि आप कुछ और ढूंढ रहे हैं। –

+0

मुझे लगता है कि आपकी प्रतिक्रिया उतनी ही अच्छी है जितनी इसे अपनी योजना दी जाती है। हम कुछ स्तर पर, हमें यह जानना होगा कि मॉडल "मर जाता है" और उसे vbo देता है। हालांकि, आरएआईआई + जीसी में, मुझे पहले से यह जानने की जरूरत नहीं है, हम कह सकते हैं "मॉडल, मुझे नहीं पता कि आप कब मरेंगे, लेकिन मुझे पता है कि जब आप करते हैं, तो आप वीबीओ छोड़ देंगे "। हम बाद में काफी कुछ नहीं कर सकते क्योंकि योजना जीसी-एड है; जो मैं मूल रूप से उम्मीद कर रहा था ... कुछ प्रकार का चालाक मैक्रो मैक था जो स्वचालित रूप से कुछ प्रकार की रेफ-गिनती में हस्तक्षेप करता था, जो वे उस प्रकार के आरएआईआई + रेफकाउंटिंग प्रदान करते थे। – anon

+0

इसमें आगे बढ़ने के लिए, निम्न स्थितियों पर विचार करें: हम एक मॉडल बनाते हैं, हम नहीं जानते कि इसे कब हटाया जाता है, लेकिन हम जानते हैं कि यह बहुत कुछ प्रदान किया गया है; इसलिए हम इसे एक वीबीओ देते हैं; इसे बहुत पास पास करें; ... और जब कोई इसका उपयोग नहीं करता है, तो यह वीबीओ को मुक्त करता है। कोड में एक भी जगह नहीं है जहां मुझे पता है "अब मैं मॉडल को मुक्त कर सकता हूं।" – anon

उत्तर

14

यदि यह सिर्फ एक बंद है, तो आप हमेशा सिर्फ एक मैक्रो dynamic-wind इर्द-गिर्द घूमती, सेटअप और पहले में और Thunks के बाद टियरडाउन (मैं यह सोचते हैं रहा है कि allocate-vertex-buffer-object और free-vertex-buffer-object अपने निर्माता और विनाशकर्ता हैं कर लिख सकते हैं यहाँ):

(define-syntax with-vertex-buffer-object 
    (syntax-rules() 
    ((_ (name arg ...) body ...) 
    (let ((name #f)) 
     (dynamic-wind 
     (lambda() (set! name (allocate-vertex-buffer-object args ...))) 
     (lambda() body ...) 
     (lambda() (free-vertex-buffer-object name) (set! name #f))))))) 

इस एक पैटर्न है कि आप वस्तुओं के विभिन्न प्रकार के एक बहुत का उपयोग करें, है, तो आप एक मैक्रो मैक्रो इस तरह की उत्पन्न करने के लिए लिख सकते हैं; और संभवतः आप एक समय में इनकी एक श्रृंखला आवंटित करना चाहते हैं, इसलिए आप शुरुआत में केवल एक ही की बजाय बाइंडिंग की सूची लेना चाहेंगे।

यहां एक ऑफ-द कफ, अधिक सामान्य संस्करण है; मैं नाम के बारे में वास्तव में यकीन नहीं है, लेकिन यह मूल विचार (मूल संस्करण में अनंत लूप ठीक करने के लिए संपादित) को दर्शाता है:

(define-syntax with-managed-objects 
    (syntax-rules() 
    ((_ ((name constructor destructor)) body ...) 
    (let ((name #f)) 
     (dynamic-wind 
     (lambda() (set! name constructor)) 
     (lambda() body ...) 
     (lambda() destructor (set! name #f))))) 
    ((_ ((name constructor destructor) rest ...) 
     body ...) 
    (with-managed-objects ((name constructor destructor)) 
     (with-managed-objects (rest ...) 
     body ...))) 
    ((_() body ...) 
    (begin body ...)))) 

और इस प्रकार आप इस का प्रयोग करेंगे:

(with-managed-objects ((vbo (allocate-vertex-buffer-object 1 2 3) 
          (free-vertext-buffer-object vbo)) 
         (frob (create-frobnozzle 'foo 'bar) 
          (destroy-frobnozzle frob))) 
    ;; do stuff ... 
) 

(let ((inner-continuation #f)) 
    (if (with-managed-objects ((foo (begin (display "entering foo\n") 1) 
            (display "exiting foo\n")) 
          (bar (begin (display "entering bar\n") (+ foo 1)) 
            (display "exiting bar\n"))) 
     (display "inside\n") 
     (display "foo: ") (display foo) (newline) 
     (display "bar: ") (display bar) (newline) 
     (call/cc (lambda (inside) (set! inner-continuation inside) #t))) 
    (begin (display "* Let's try that again!\n") 
      (inner-continuation #f)) 
    (display "* All done\n"))) 
:

यहाँ एक उदाहरण यह बाहर निकलने और गुंजाइश निरंतरता का उपयोग कर फिर से डालने (यह एक नहीं बल्कि काल्पनिक उदाहरण है, क्षमा याचना करता है, तो नियंत्रण प्रवाह का पालन करने के लिए कठिन एक सा है) सहित, काम यह दर्शाता है कि है

यह मुद्रित करना चाहिए:

 
entering foo 
entering bar 
inside 
foo: 1 
bar: 2 
exiting bar 
exiting foo 
* Let's try that again! 
entering foo 
entering bar 
exiting bar 
exiting foo 
* All done 

call/cc बस call-with-current-continuation का संक्षिप्त नाम है; यदि आपकी योजना में कम से कम नहीं है तो लंबे फॉर्म का उपयोग करें।

अद्यतन: जैसा कि आपने अपनी टिप्पणियों में स्पष्ट किया है, आप संसाधनों को प्रबंधित करने का एक तरीका ढूंढ रहे हैं जिन्हें किसी विशेष गतिशील संदर्भ से वापस किया जा सकता है। इस मामले में, आपको फाइनलाइज़र का उपयोग करना होगा; एक फाइनलाइज़र एक ऐसा कार्य होता है जिसे जीसी ने साबित कर दिया है कि इसे किसी और जगह से नहीं पहुंचा जा सकता है। फाइनलर मानक नहीं हैं, लेकिन अधिकांश परिपक्व योजना प्रणालियों में, कभी-कभी अलग-अलग नामों के तहत होते हैं। उदाहरण के लिए, पीएलटी योजना में, Wills and Executors देखें।

आपको यह ध्यान में रखना चाहिए कि योजना में, एक गतिशील संदर्भ फिर से दर्ज किया जा सकता है; यह अधिकांश अन्य भाषाओं से अलग है, जिसमें आप अपवादों का उपयोग करके किसी भी मनमानी बिंदु पर गतिशील संदर्भ से बाहर निकलने में सक्षम हो सकते हैं, लेकिन आप पुनः दर्ज नहीं कर सकते हैं।ऊपर दिए गए मेरे उदाहरण में, मैंने गतिशील संदर्भ छोड़ते समय संसाधनों को हटाने के लिए dynamic-wind का उपयोग करने का एक भरोसेमंद दृष्टिकोण प्रदर्शित किया, और यदि आप दोबारा दर्ज करते हैं तो उन्हें फिर से आवंटित करें। यह कुछ संसाधनों के लिए उपयुक्त हो सकता है, लेकिन कई संसाधनों के लिए यह उचित नहीं होगा (उदाहरण के लिए, फ़ाइल को फिर से खोलना, अब आप गतिशील संदर्भ दोबारा दर्ज करते समय फ़ाइल की शुरुआत में होंगे), और हो सकता है महत्वपूर्ण ओवरहेड

टेलर कैंपबेल (हाँ, एक संबंध है) an article in his blag (200 9-03-28 प्रविष्टि) इस मुद्दे को संबोधित करते हुए, और सटीक अर्थशास्त्र के आधार पर कुछ विकल्प पेश करते हैं जो आप चाहते हैं। उदाहरण के लिए, वह एक unwind-protext रूप प्रदान करता है जो सफाई प्रक्रिया को तब तक नहीं बुलाएगा जब तक कि गतिशील संदर्भ को पुन: दर्ज नहीं किया जा सके, जिसमें संसाधन पहुंच योग्य है।

तो, इसमें उपलब्ध कई अलग-अलग विकल्प शामिल हैं। आरएआईआई के लिए कोई सटीक मैच नहीं है, क्योंकि योजना एक बहुत ही अलग भाषा है और इसमें बहुत अलग बाधाएं हैं। यदि आपके पास अधिक विशिष्ट उपयोग केस है, या संक्षेप में उपयोग किए गए उपयोग मामले पर अधिक जानकारी है, तो मैं आपको कुछ और विशिष्ट सलाह प्रदान कर सकता हूं।

संबंधित मुद्दे