2014-08-28 8 views
5

का नक्शा मुझे थ्रेड-सुरक्षित नक्शा बनाने की ज़रूरत है, जहां मेरा मतलब है कि प्रत्येक मान को स्वतंत्र रूप से म्यूटेक्स किया जाना चाहिए। उदाहरण के लिए, मुझे 2 अलग-अलग धागे से एक ही समय में map["abc"] और map["vf"] प्राप्त करने में सक्षम होना चाहिए। डेटा के लिए एक और हर कुंजी के लिए म्युटेक्स के लिए एक:म्यूटेक्स सी ++ 11

मेरा विचार दो नक्शे बनाने के लिए है

class cache 
{ 
private: 
.... 

    std::map<std::string, std::string> mainCache; 
    std::map<std::string, std::unique_ptr<std::mutex> > mutexCache; 
    std::mutex gMutex; 
..... 
public: 
    std::string get(std::string key); 

}; 
std::string cache::get(std::string key){ 
    std::mutex *m; 
    gMutex.lock(); 
    if (mutexCache.count(key) == 0){ 
     mutexCache.insert(new std::unique_ptr<std::mutex>); 
    } 
    m = mutexCache[key]; 
    gMutex.unlock(); 
} 

मुझे लगता है कि मैं नहीं नक्शा स्ट्रिंग से म्युटेक्स को, बना सकते हैं कोई नकल निर्माता है, क्योंकि std::mutex में और मुझे std::unique_ptr का उपयोग करना होगा; लेकिन जब मैं इसे संकलित करता हूं तो मुझे मिलता है:

/home/user/test/cache.cpp:7: error: no matching function for call to 'std::map<std::basic_string<char>, std::unique_ptr<std::mutex> >::insert(std::unique_ptr<std::mutex>*)' 
     mutexCache.insert(new std::unique_ptr<std::mutex>); 
                 ^

मैं इस समस्या को कैसे हल करूं?

उत्तर

9

साथ mutexCache.insert(new std::unique_ptr<std::mutex>) बदलें:

mutexCache.emplace(key, new std::mutex); 

सी ++ 14 में, आप कह चाहिए:

mutexCache.emplace(key, std::make_unique<std::mutex>()); 

समग्र कोड, बहुत शोर और असजीला है, हालांकि। यह शायद इस तरह दिखना चाहिए:

std::string cache::get(std::string key) 
{ 
    std::mutex * inner_mutex; 

    { 
     std::lock_guard<std::mutex> g_lk(gMutex); 

     auto it = mutexCache.find(key); 
     if (it == mutexCache.end()) 
     { 
      it = mutexCache.emplace(key, std::make_unique<std::mutex>()).first; 
     } 
     inner_mutex = it->second.get(); 
    } 

    { 
     std::lock_guard<std::mutex> c_lk(*inner_mutex); 
     return mainCache[key]; 
    } 
} 
+1

+1 'std :: make_unique ' –

+3

FWIW के लिए, आप 'का उपयोग करना चाहिए सी ++ 11 भी में make_unique'। –

4

तुम क्यों पहली जगह में एक std::unique_ptr उपयोग करने के लिए की जरूरत है?

मुझे वही समस्या थी जब मुझे ऑब्जेक्ट्स std::map बनाना था। मुद्दा यह है कि std::mutex न तो कॉपी करने योग्य और न ही जंगम है, इसलिए मुझे इसे "जगह में" बनाने की आवश्यकता है।

मैं केवल emplace का उपयोग नहीं कर सका क्योंकि यह डिफ़ॉल्ट रूप से निर्मित मानों के लिए सीधे काम नहीं करता है। वहाँ std::piecewise_construct उस तरह उपयोग करने के लिए एक विकल्प है:

map.emplace(std::piecewise_construct, std::make_tuple(key), std::make_tuple()); 

लेकिन यह IMO जटिल और कम पठनीय है।

मेरे समाधान बहुत सरल है - बस operator[] का उपयोग करें - यह उसके डिफ़ॉल्ट निर्माता का उपयोग कर मूल्य बनाने और इसे करने के लिए एक संदर्भ वापस आ जाएगी। या यह केवल एक नया निर्माण किए बिना पहले से मौजूद आइटम के संदर्भ को ढूंढ और वापस कर देगा।

std::map<std::string, std::mutex> map; 

std::mutex& GetMutexForFile(const std::string& filename) 
{ 
    return map[filename]; // constructs it inside the map if doesn't exist 
}