2013-04-08 24 views
12

मेरे पास एक थ्रेडेड क्लास है जिसमें से मैं कभी-कभी एक पॉइंटर को एक आवृत्ति चर प्राप्त करना चाहता हूं। मैं इस एक्सेस को म्यूटेक्स द्वारा संरक्षित करना चाहता हूं ताकि थ्रेड को इस संसाधन तक पहुंचने से अवरुद्ध कर दिया जाए जब तक कि क्लाइंट अपने सूचक के साथ समाप्त न हो जाए।मैं एक स्मार्ट पॉइंटर कैसे बना सकता हूं जो एक म्यूटेक्स को ताले और अनलॉक करता है?

मेरा प्रारंभिक दृष्टिकोण ऑब्जेक्ट्स की एक जोड़ी वापस करना है: संसाधन के लिए एक पॉइंटर और mutex पर लॉक ऑब्जेक्ट में एक साझा_ptr। यह shared_ptr लॉक ऑब्जेक्ट का एकमात्र संदर्भ रखता है, इसलिए जब यह गुंजाइश से बाहर हो जाता है तो म्यूटेक्स को अनलॉक किया जाना चाहिए। कुछ इस तरह:

void A::getResource() 
{ 
    Lock* lock = new Lock(&mMutex); 
    return pair<Resource*, shared_ptr<Lock> >(
     &mResource, 
     shared_ptr<Lock>(lock)); 
} 

यह समाधान आदर्श की तुलना में कम है, क्योंकि यह ग्राहक वस्तुओं के पूरे जोड़ी पर धारण करने के लिए की आवश्यकता है। इस तरह व्यवहार धागा सुरक्षा टूट जाता है:

Resource* r = a.getResource().first; 

इसके अलावा, इस के अपने खुद के कार्यान्वयन deadlocking है और मैं निर्धारित करने में कठिनाई हो रही हूँ क्यों, इसलिए वहाँ अन्य बातों के साथ यह गलत हो सकता है।

मैं जो साझा करना चाहता हूं वह एक साझा_ptr है जिसमें लॉक को इंस्टेंस वैरिएबल के रूप में शामिल किया गया है, संसाधन को एक्सेस करने के साधनों के साथ बाध्यकारी है। ऐसा लगता है कि एक स्थापित डिज़ाइन पैटर्न होना चाहिए लेकिन कुछ शोध करने के बाद मुझे आश्चर्य हुआ कि यह काफी कठिन हो गया है।

मेरे प्रश्न हैं:

  • इस प्रतिरूप का एक आम कार्यान्वयन है?
  • क्या कोई साझा_प्टर के अंदर एक म्यूटक्स डालने के साथ कोई समस्या है जो मैं देख रहा हूं कि इस पैटर्न को व्यापक रूप से रोकने से रोकें?
  • क्या इस पैटर्न को लागू करने के लिए मेरे स्वयं के साझा_प्टर वर्ग को लागू करने का कोई अच्छा कारण नहीं है?

(नायब मैं एक codebase क्यूटी का उपयोग करता है लेकिन दुर्भाग्य से इस मामले में बढ़ावा उपयोग नहीं कर सकते उस पर काम कर रहा हूँ। हालांकि, को बढ़ावा देने से जुड़े सवालों के जवाब सामान्य ब्याज की अभी भी कर रहे हैं।)

+0

रिव और जोनंतान वाकीली के दोनों जवाब दिलचस्प और मूल्यवान हैं। मैं रिज के साथ जा रहा हूं क्योंकि जवाब में कुछ पूर्ण सहयोगी रूप से संपादित कोड होना अच्छा लगता है। –

उत्तर

7

मैं अगर यकीन नहीं है वहाँ किसी भी मानक कार्यान्वयन कर रहे हैं, लेकिन जब से मैं पसंद बिना किसी कारण के लिए फिर से लागू करने सामान, यहाँ एक संस्करण है कि काम करना चाहिए है (यह मानते हुए आप इस तरह के संकेत दिए गए कॉपी करने के लिए सक्षम होने के लिए नहीं करना चाहते हैं):

template<class T> 
class locking_ptr 
{ 
public: 
    locking_ptr(T* ptr, mutex* lock) 
    : m_ptr(ptr) 
    , m_mutex(lock) 
    { 
    m_mutex->lock(); 
    } 
    ~locking_ptr() 
    { 
    if (m_mutex) 
     m_mutex->unlock(); 
    } 
    locking_ptr(locking_ptr<T>&& ptr) 
    : m_ptr(ptr.m_ptr) 
    , m_mutex(ptr.m_mutex) 
    { 
    ptr.m_ptr = nullptr; 
    ptr.m_mutex = nullptr; 
    } 

    T* operator ->() 
    { 
    return m_ptr; 
    } 
    T const* operator ->() const 
    { 
    return m_ptr; 
    } 
private: 
    // disallow copy/assignment 
    locking_ptr(locking_ptr<T> const& ptr) 
    { 
    } 
    locking_ptr& operator = (locking_ptr<T> const& ptr) 
    { 
    return *this; 
    } 
    T* m_ptr; 
    mutex* m_mutex; // whatever implementation you use 
}; 
+0

+1 इसे ऐसा करना चाहिए - शायद असाइनमेंट अक्षम करें और एक चालक कन्स्ट्रक्टर जोड़ें? – stijn

+0

निश्चित रूप से, आप 'ऑपरेटर =' को निजी सेक्शन में ले जाकर असाइनमेंट अक्षम कर सकते हैं, लेकिन जब तक म्यूटेक्स नेस्टेड लॉक का समर्थन करता है तब तक यह सुरक्षित होना चाहिए। जोड़ा चालक जोड़ा गया। – riv

+0

दो टाइपो फिक्स्ड; आप '= delete' कीवर्ड के साथ असाइनमेंट अक्षम कर सकते हैं, लेकिन यह मेरे विजुअल स्टूडियो द्वारा समर्थित नहीं है। – riv

3

आप का वर्णन कर रहे हैंमें केवलिन हेनी द्वारा वर्णित EXECUTE AROUND POINTER पैटर्न की एक भिन्नता

मेरे पास exec_around.h पर एक प्रोटोटाइप कार्यान्वयन है लेकिन मैं गारंटी नहीं दे सकता कि यह सभी मामलों में सही ढंग से काम करता है क्योंकि यह एक काम प्रगति पर है। इसमें एक फ़ंक्शन mutex_around शामिल है जो एक ऑब्जेक्ट बनाता है और इसे एक स्मार्ट पॉइंटर में लपेटता है जो एक्सेस होने पर म्यूटक्स को लॉक करता है और अनलॉक करता है।

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

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