मैं एक प्रकार की डेटाबेस लाइब्रेरी लिख रहा हूं। मूलभूत निर्यात यह निम्न है:एसिंक्रोनस अपवादों का नेस्टेड मास्किंग
withDatabase :: FilePath -> (DBHandle -> IO a) -> IO a
जो स्वचालित रूप से डेटाबेस हैंडल के जीवनकाल का प्रबंधन करता है।
आंतरिक रूप से, withDatabase
से नियंत्रण का उपयोग करता है। नियंत्रण 0 अपवाद।
withDatabase path f = bracket (openDatabase path) closeDatabase f
मेरी विशिष्ट मामले में, openDatabase
कुछ महत्वपूर्ण आई/ओ प्रदर्शन कर सकते हैं और इस तरह एक लंबे समय के लिए ब्लॉक। इस कारण से, मैं इसके कुछ हिस्सों को असीमित अपरिवर्तित अपवादों के साथ चलाने के लिए चाहता हूं। एक (सरलीकृत) कार्यान्वयन हो सकता है:
openDatabase :: FilePath -> IO DBHandle
openDatabase path = mask $ \restore -> do
h <- openFile path ReadWriteMode
restore (doLongStuff h) `onException` (hClose h)
...
return (DBHandle h)
मुझे यकीन है कि इस कोड प्रभाव मैं इरादा उत्पादन नहीं कर रहा हूँ।
के withDatabase
पर वापस नजर डालते हैं, इस बार अपनी परिभाषा के साथ bracket
की जगह:
\- withDatabase
\- mask
\- openDatabase
\- mask
\- restore
\- doLongStuff
प्रलेखन के लिए:
withDatabase path f = mask $ \restore -> do
h <- openDatabase path
r <- restore (f h) `onException` closeDatabase h
_ <- closeDatabase h
return r
निष्पादन में एक निश्चित बिंदु पर, कॉल स्टैक निम्न हो जाता है नियंत्रण। अपवाद मॉड्यूल में नेस्टेड कॉल के बारे में कुछ है mask
:
ध्यान दें कि मुखौटा के तर्क को पारित करने वाली पुनर्स्थापना कार्रवाई अनिवार्य रूप से एसिंक्रोनस अपवादों को अनमास्क नहीं करती है, यह केवल मुखौटा स्थिति को संलग्न संदर्भ के लिए पुनर्स्थापित करती है। इस प्रकार यदि एसिंक्रोनस अपवाद पहले ही मास्क किए गए हैं, तो मास्क का उपयोग अपवादों को फिर से खोलने के लिए नहीं किया जा सकता है।
इस वर्णन की मेरी समझ यह है कि doLongStuff
एसिंक्रोनस अपवादों के साथ काम करेगा, जैसा कि मैं चाहूंगा, अनब्लॉक किया गया था।
मेरा असली कोड में, मैं openFile
है और न ही doLongStuff
न स्थानांतरित नहीं कर सकते openDatabase
से बाहर: वास्तव में, openDatabase
फ़ाइलों के किसी भी संख्या को खोलने और/या पहले "निर्णय लेने से" जो संभाल यह withDatabase
पर लौटने के लिए चाहता है विभिन्न मैं/ओएस प्रदर्शन कर सकते हैं । इस दबाव को देखते हुए, क्या doLongStuff
को अवरुद्ध करने का कोई तरीका है भले ही यह नेस्टेड mask
कॉल के अंदर चलने के लिए होता है?