2010-10-09 13 views
7

का उपयोग करने का उदाहरण मेरे पास एक बहुप्रचारित सर्वर एप्लिकेशन है जिसे कुछ साझा स्मृति पर म्यूटेक्स लॉक की आवश्यकता होती है।बूस्ट अपग्रेड करने योग्य म्यूटेक्स

साझा स्मृति मूल रूप से STL नक्शे आदि समय मैं सिर्फ नक्शे से पढ़ रहा हूँ की

बहुत हैं। लेकिन, मुझे कभी-कभी इसे जोड़ने की भी आवश्यकता है।

उदा टाइपपीफ std :: मानचित्र संदेश मैप; संदेश मैप संदेश; बूस्ट: shared_mutex access_;

void ProcessMessage(Message* message) 
{ 
    // Access message... read some stuff from it message->... 

    UUID id = message->GetSessionID(); 

    // Need to obtain a lock here. (shared lock? multiple readers) 
    // How is that done? 
    boost::interprocess::scoped_lock(access_); 

    // Do some readonly stuff with msgmap 
    MessageMap::iterator it = msgmap.find(); 
    // 

    // Do some stuff... 

    // Ok, after all that I decide that I need to add an entry to the map. 
    // how do I upgrade the shared lock that I currently have? 
    boost::interprocess::upgradable_lock 


    // And then later forcibly release the upgrade lock or upgrade and shared lock if I'm not looking 
    // at the map anymore. 
    // I like the idea of using scoped lock in case an exception is thrown, I am sure that 
    // all locks are released. 
} 

संपादित करें: मैं अलग ताला प्रकार भ्रमित हो सकता है।

साझा/अपग्रेड और अनन्य के बीच क्या अंतर है। यानी मैं स्पष्टीकरण को समझ नहीं पा रहा हूं। ऐसा लगता है जैसे आप बहुत सारे पाठकों को अनुमति देना चाहते हैं, एक साझा पहुंच वह है जिसे आप प्राप्त करना चाहते हैं। और अपनी साझा मेमोरी को लिखने के लिए आपको केवल अपग्रेड एक्सेस की आवश्यकता है। या आपको अनन्य की आवश्यकता है? बूस्ट में स्पष्टीकरण कुछ भी स्पष्ट है।

अपग्रेड एक्सेस प्राप्त है क्योंकि आप लिख सकते हैं। लेकिन साझा किया गया मतलब है कि आप निश्चित रूप से नहीं लिखेंगे कि इसका क्या अर्थ है?

संपादित करें: मुझे बताएं कि मैं थोड़ा और स्पष्टता के साथ क्या करना चाहता हूं। मैं अभी तक जवाब से खुश नहीं हूँ।

यहां फिर से उदाहरण है लेकिन कुछ कोड के उदाहरण के साथ मैं भी उपयोग कर रहा हूं। बस एक उदाहरण, वास्तविक कोड नहीं।

typedef boost::shared_mutex Mutex; 
typedef boost::shared_lock<Mutex> ReadLock; 
typedef boost::unique_lock<Mutex> WriteLock; 
Mutex mutex; 
typedef map<int, int> MapType; // Your map type may vary, just change the typedef 
MapType mymap; 

void threadoolthread() // There could be 10 of these. 
{ 
    // Add elements to map here 
    int k = 4; // assume we're searching for keys equal to 4 
    int v = 0; // assume we want the value 0 associated with the key of 4 

    ReadLock read(mutex); // Is this correct? 
    MapType::iterator lb = mymap.lower_bound(k); 
    if(lb != mymap.end() && !(mymap.key_comp()(k, lb->first))) 
    { 
     // key already exists 
    } 
    else 
    { 
     // Acquire an upgrade lock yes? How do I upgrade the shared lock that I already  have? 
     // I think then sounds like I need to upgrade the upgrade lock to exclusive is that correct as well? 

     // Assuming I've got the exclusive lock, no other thread in the thread pool will be able to insert. 
     // the key does not exist in the map 
     // add it to the map 
     { 
      WriteLock write(mutex, boost::adopt_lock_t()); // Is this also correct? 
      mymap.insert(lb, MapType::value_type(k, v)); // Use lb as a hint to insert, 
                 // so it can avoid another lookup 
     } 
     // I'm now free to do other things here yes? what kind of lock do I have here, if any? does the readlock still exist? 
    } 

उत्तर

11

आपने कहा था कि आपके आवेदन, थ्रेड है, ताकि आप को बढ़ावा देने का उपयोग करना चाहिए :: धागा बढ़ावा नहीं :: इंटरप्रोसेस।

प्रलेखन (परीक्षण नहीं) आप इसे इस तरह से करना चाहिए से:,

typedef boost::thread::shared_mutex shared_mutex; 
boost::thread::upgrade_lock<shared_mutex> readLock(access_); 

// Read access... 

boost::thread::upgrade_to_unique_lock<shared_mutex> writeLock(readLock); 

// Write access.. 

भी ध्यान रखें कि आप it प्राप्त करते समय आप पढ़ने के लिए पहुंच के लिए ताला तो कोई इस नोड हटा सकते हैं और यह अब मान्य नहीं है जब आप लेखन खंड में जाते हैं। गलत, क्षमा करें।

संपादित करें: मुझे लगता है कि बढ़ावा में explanation स्पष्ट है। के वैसे भी आप के लिए यह अलग तरीके से व्यक्त कोशिश करते हैं:

वहाँ म्युटेक्स अवधारणाओं के तीन मुख्य प्रकार (मैं TimedLockable गिनती नहीं है, क्योंकि यह आपके प्रश्न से संबंधित नहीं है) कर रहे हैं:

  • लॉक — सिर्फ एक सरल, अनन्य स्वामित्व म्यूटेक्स। अगर कोई लॉक() एस है तो कोई भी इसे तब तक लॉक नहीं कर सकता है जब तक कि मालिक अनलॉक नहीं करता है()। boost :: thread :: mutex इस अवधारणा को लागू करता है। RAII शैली में इस अवधारणा को लॉक करने के लिए अधिक जटिल इंटरफ़ेस के लिए lock_guard या unique_lock का उपयोग करें।
  • साझा लॉक करने योग्य — अतिरिक्त "साझा" स्वामित्व वाला लॉक करने योग्य है। आप लॉक() या लॉक_श्रेड() के साथ साझा स्वामित्व के साथ अनन्य स्वामित्व प्राप्त कर सकते हैं।यदि आप साझा भाग को लॉक करते हैं तो आप अपने स्वामित्व को अनन्य में अपग्रेड नहीं कर सकते हैं। आपको अनलॉक_श्रेड() और लॉक() को दोबारा करने की आवश्यकता है जिसका अर्थ है कि कोई और अनलॉक_श्रेड() और लॉक() के बीच संरक्षित संसाधन को संशोधित कर सकता है। यह तब उपयोगी होता है जब आप प्राथमिकता को जानते हैं कि संसाधन के लिए आपको किस प्रकार की पहुंच होगी। shared_mutex इस अवधारणा को लागू करता है। साझा स्वामित्व प्राप्त करने के लिए अनन्य स्वामित्व और साझा_लॉक प्राप्त करने के लिए lock_guard या unique_lock का उपयोग करें।
  • अपग्रेड लॉक करने योग्य — साझा लॉक करने योग्य है जो आपको साझा स्वामित्व से अनलॉक किए बिना अनन्य स्वामित्व में अपग्रेड करने की अनुमति देता है। shared_mutex भी इस अवधारणा को लागू करता है। आप अनन्य या साझा स्वामित्व प्राप्त करने के लिए उपरोक्त ताले का उपयोग कर सकते हैं। अपग्रेड करने योग्य साझा स्वामित्व प्राप्त करने के लिए upgrade_lock का उपयोग करें और इसे upgrade_to_unique_lock के साथ अपग्रेड करें।
+0

क्षमा करें मुझे लगता है कि शायद मैं boost :: upgrade_lock और boost :: upgrade_to_unique_lock का उपयोग करना चाहता हूं। शायद आप उनके बीच के अंतर को समझा सकते हैं। मेरा संपादित प्रश्न देखें। – Matt

+0

@ मैट एच: संपादित उत्तर देखें। – ybungalobill

+0

अपग्रेड लॉक करने योग्य के साथ उस राज्य में केवल एक ही धागा हो सकता है लेकिन कई साझा किए जा सकने योग्य में यह सही है? इसलिए अपग्रेड लॉक को अनन्य लॉक बनने के लिए सभी साझा लॉक को अनलॉक करने की आवश्यकता है? – Matt

5

यदि आप केवल एक ही प्रक्रिया का उपयोग कर रहे हैं तो आप boost-interprocess नहीं चाहते हैं। चूंकि लाइब्रेरी का नाम तात्पर्य है, इसका उपयोग इंटर-प्रोसेस कम्युनिकेशन (आईपीसी) के लिए किया जाता है। आप शायद boost-threadmutex and locking concepts का उपयोग करना चाहते हैं।

#include <boost/thread/locks.hpp> 
#include <boost/thread/shared_mutex.hpp> 

int 
main() 
{ 
    typedef boost::shared_mutex Mutex; 
    typedef boost::shared_lock<Mutex> ReadLock; 
    typedef boost::unique_lock<Mutex> WriteLock; 
    Mutex mutex; 

    { 
     // acquire read lock 
     ReadLock read(mutex); 

     // do something to read resource 
    } 

    { 
     // acquire write lock 
     WriteLock write(mutex, boost::adopt_lock_t()); 

     // do something to write resource 
    } 
} 

वहाँ बढ़ावा मेलिंग सूची इस रूप में अच्छी तरह समझा पर एक post है।

+1

संपादित करें: धन्यवाद सैम। क्या आप उपरोक्त मेरे उदाहरण पर एक नज़र डाल सकते हैं जिसे मैंने प्रश्न के निचले हिस्से में संपादित किया है। क्या यह सही उपयोग होगा? – Matt

+1

@ मैट, आपके मामले में रीड लॉक को 'थ्रेडूलथ्रेड' दर्ज करते समय बिना शर्त अधिग्रहण किया जाता है, मुझे लगता है कि आप 'boost :: upgrade_to_unique_lock' का उपयोग करना चाहते हैं जो ybungalobill [वर्णित] है [http://stackoverflow.com/questions/3896717/उदाहरण के-कैसे के लिए उपयोग-बढ़ावा-पदोन्नत किया जा सकता-mutexes/3896816 # 3896816)। हालांकि, मैंने कभी भी 'boost :: adopt_lock_t()' का उपयोग नहीं किया है, इसलिए मैं व्यवहार से परिचित नहीं हूं, शायद यह काम करता है। –

+0

थ्रेड पूल फ़ंक्शन की शुरुआत में upgrade_to_unique_lock का उपयोग नहीं करेगा, इसका मतलब है कि थ्रेड पूल में केवल एक थ्रेड एक समय में चल सकता है? – Matt

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