2015-12-20 10 views
5

सी ++ में हैश फ़ंक्शन क्लास ऑब्जेक्ट्स <functional> थ्रेड सुरक्षित में घोषित हैं? उदाहरण के लिए, क्या यह फ़ंक्शन एकाधिक थ्रेड से कॉल करना सुरक्षित है?सी ++ 11 std :: हैश फ़ंक्शन ऑब्जेक्ट क्लास थ्रेड सुरक्षा

size_t hash1(const std::string& s) { 
    std::hash<std::string> str_hash; 
    return str_hash(s); 
} 

या, यदि एक एक वैश्विक वस्तु std::hash<std::string> str_hash_global; है, तो यह सुरक्षित एक से अधिक थ्रेड से यह दूसरा समारोह कॉल करने के लिए है?

size_t hash2(const std::string& s) { 
    return str_hash_global(s); 
} 
+0

अन्य विचार अलग-अलग हैं, सुनिश्चित करें कि स्ट्रिंग स्वयं को समेकित रूप से संशोधित नहीं किया जा रहा है जबकि इसकी हैश की गणना की गई है। –

उत्तर

6

मानक पुस्तकालय का वादा किया है कि आप केवल कॉल एक मानक पुस्तकालय वस्तु पर const -qualified सदस्य काम करता है, मानक पुस्तकालय कोड एक डेटा दौड़ का कारण नहीं है अगर (सीएफ [res.on.data.races ])।

मानक टेम्पलेट std::hash, साथ ही अपने सभी अनुमेय विशेषज्ञताओं, साथ ही किसी भी उपयोगकर्ता द्वारा प्रदान की functor कि Hash आवश्यकताओं को पूरा ([hash.requirements]) एक const -qualified कॉल ऑपरेटर होना आवश्यक आवश्यकताओं के कारण, और इस प्रकार पुस्तकालय द्वारा प्रदत्त std::hash विशेषज्ञता का उपयोग किसी दौड़ का कारण नहीं बनना चाहिए। इसके अलावा, [namespace.std] के कारण, कार्यक्रम-प्रदान की गई विशेषज्ञता को समान आवश्यकताओं को पूरा करना होगा।

अंत में, मुझे लगता है कि आप आमतौर पर रिकर्सिवली const कॉल करने के लिए अपील द्वारा जाति-साहस की गारंटी देता है प्रयोग करेंगे: आप एक से अधिक थ्रेड समवर्ती मानचित्र गए मानों को देखें, तो वे नक्शे के const इंटरफ़ेस का उपयोग करने के लिए ऊपर पुस्तकालय आह्वान करने के लिए है नियम, लेकिन फिर मानचित्र केवल हैशर (या एक निजी प्रति) के निरंतर मूल्य का उपयोग करने के लिए मिलता है, और इसलिए यह केवल रेस-फ्री हैश कंप्यूटेशंस ही कर सकता है। चाहे एक नस्ल गैर-कॉन्स्ट कॉल ऑपरेटर मौजूद है उस बिंदु पर अपरिपक्व है।

+0

'आवश्यकताओं के कारण एक कॉन्स्ट-क्वालिफाइड कॉल ऑपरेटर होना चाहिए' मानक के किस भाग की आवश्यकता है? मैं यह कहने के लिए कुछ ढूंढ रहा था, और इसे नहीं मिला। वहां "मूल्य वापस कार्यक्रम की अवधि के लिए तर्क 'के' पर निर्भर करेगा", लेकिन यह सीधे नहीं कहता है कि "ऑपरेटर()' को कॉन्स-क्वालिफाइड होना चाहिए " –

+0

@ इगोरंडंडनिक: यह कहता है" एच' एक (संभवतः 'const') मान है"। –

+1

आह, हाँ, तो यह करता है। "' h' सटीक होने के लिए प्रकार (संभावित रूप से कॉन्स) 'एच'' का मान है। मुझे लगता है कि अभी भी एक वर्ग को सख्ती से नहीं रोकता है जो 'ऑपरेटर()', एक कॉन्स और एक गैर-कॉन्स के दो अधिभार प्रदान करता है (हालांकि यह स्पष्ट नहीं है कि कोई भी ऐसा क्यों करना चाहेगा)। –

2

वही "थ्रेड-सुरक्षा" नियम सभी std :: lib प्रकारों के लिए यहां लागू होते हैं।

पहला संस्करण थ्रेड-सुरक्षित होने की गारंटी है क्योंकि धागे के बीच कोई चर साझा नहीं किया जाता है।

दूसरे को operator() कहा जाता है जो const कहलाता है तो कोई भी डेटा रेस नहीं होने की गारंटी है। यह अनिर्दिष्ट है कि कार्यान्वयन (आवश्यक) एक के अलावा hash<T>::operator() के गैर-कॉन्स ओवरलोड को संभावित रूप से गैर-थ्रेड-सुरक्षित प्रदान करता है। यदि आपका global_str_hash कॉन्स है, या आप इसका उपयोग करने से पहले इसे स्थिर करने के लिए डाले हैं, तो आप गारंटी देते हैं किका उपयोग किया जाएगा।

दूसरे संस्करण को करने का कोई कारण नहीं है, यह सिर्फ मूर्खतापूर्ण है, लेकिन व्यावहारिक रूप से यह सुरक्षित होना चाहिए क्योंकि कोई मानक लाइब्रेरी कार्यान्वयन hash::operator() का एक कठोर गैर-कॉन्स अधिभार प्रदान करने की संभावना है, वे केवल एक कॉन्स्ट अधिभार प्रदान करेंगे , जो थ्रेड-सुरक्षित होना चाहिए।

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