2013-06-01 6 views
34

मैं एंथनी विलियम्स "एक्शन में सी ++ कन्करेंसी" के माध्यम से और अध्याय 5, जो नए बहु सूत्रण अवगत स्मृति मॉडल और परमाणु संचालन के बारे में बात करती है में पढ़ रहा हूँ, और वह कहता है:क्या std :: atomic <std::string> उचित काम करता है?

आदेश के लिए std::atomic<UDT> उपयोग करने के लिए कुछ उपयोगकर्ता परिभाषित UDT, इस प्रकार के पास त्रिभुज कॉपी असाइनमेंट ऑपरेटर होना चाहिए।

मैं यह समझ के रूप में, इसका मतलब है कि हम std::atomic<UDT> उपयोग कर सकते हैं अगर सच निम्नलिखित रिटर्न:

std::is_trivially_copyable<UDT>::value 

इस तर्क के आधार हम std::atomic के लिए एक टेम्पलेट तर्क के रूप में std::string उपयोग करने में सक्षम नहीं होना चाहिए और यह सही ढंग से काम करता है।

हालांकि, निम्नलिखित कोड को संकलित करता है और उम्मीद उत्पादन के साथ चलाता है:

#include <atomic> 
#include <thread> 
#include <iostream> 
#include <string> 

int main() 
{ 
    std::atomic<std::string> atomicString; 

    atomicString.store("TestString1"); 

    std::cout << atomicString.load() << std::endl; 

    atomicString.store("TestString2"); 

    std::cout << atomicString.load() << std::endl; 

    return 0; 
} 

इस अपरिभाषित व्यवहार का मामला जो सिर्फ अपेक्षा के अनुरूप व्यवहार करने के लिए होता है?

अग्रिम धन्यवाद!

+1

आपका कंपाइलर (और stdlib का आपका कार्यान्वयन) क्या है? मैं इसे संकलक नहीं बना सकता [यहां] (http://coliru.stacked-crooked.com/view?id=0ce3b66093e9a0a59d5179429373eea7-e54ee7a04e4b807da0930236d4cc94dc), और वास्तव में मैं –

+0

@AndyProwl की अपेक्षा कर रहा था, मैं वीएस 2012 का उपयोग कर रहा हूं पल, नवंबर सीटीपी के बिना। –

+2

जैसा कि आप इसका उपयोग कर रहे हैं, मुझे कोई समस्या देखने की उम्मीद नहीं होगी। समस्या तब उत्पन्न होगी जब दो (या अधिक) थ्रेड एक ही स्ट्रिंग को एक ही समय में संशोधित करने का प्रयास कर रहे थे। उस बिंदु पर, 'स्ट्रिंग' का गैर-तुच्छ ऑपरेटर समस्या का कारण बनना शुरू कर देगा। बस 'std :: atomic' में कुछ लपेटने से कोड को तोड़ने की संभावना नहीं है जो इसके बिना ठीक होगा। साथ ही, इसके नियमों का पालन किए बिना, यह कोड को मदद करने वाला नहीं है जो इसके बिना टूटा जाएगा। –

उत्तर

38

मानक std::atomic<std::string> का विशेषज्ञता निर्दिष्ट नहीं करता है, इसलिए सामान्य template <typename T> std::atomic<T> लागू होता है। 2 9 .5 [atomics.types.generic] पी 1 कहता है:

एक सामान्य वर्ग टेम्पलेट परमाणु है। टेम्पलेट तर्क टी का प्रकार तुच्छ रूप से कॉपी करने योग्य (3.9) होगा।

कोई बयान नहीं है कि कार्यान्वयन को इस आवश्यकता के उल्लंघन का निदान करना चाहिए। तो या तो (ए) std::atomic<std::string> का उपयोग अपरिभाषित व्यवहार का आह्वान करता है, या (बी) आपका कार्यान्वयन एक अनुरूप विस्तार के रूप में std::atomic<std::string> प्रदान करता है।

std::atomic<T> (http://msdn.microsoft.com/en-us/library/vstudio/hh874651.aspx) के लिए MSDN पेज को देखते हुए, यह स्पष्ट रूप से आवश्यकता है कि तुच्छता copyable हो T उल्लेख करता है, और यह कुछ भी std::atomic<std::string> के बारे में विशिष्ट कहना नहीं है। यदि यह एक विस्तार है, तो यह अनियंत्रित है। मेरा पैसा अपरिभाषित व्यवहार पर है।

विशेष रूप से, 17.6.4.8/1 लागू होता है (with thanks to Daniel Krügler for setting me straight):

कुछ मामलों (प्रतिस्थापन काम करता है, हैंडलर काम करता है, मानक पुस्तकालय टेम्पलेट घटकों का दृष्टांत के लिए इस्तेमाल किया प्रकार पर परिचालन) में, सी ++ मानक पुस्तकालय पर निर्भर करता है एक सी ++ कार्यक्रम द्वारा आपूर्ति घटक। यदि ये घटक उनकी आवश्यकताओं को पूरा नहीं करते हैं, तो मानक कार्यान्वयन पर कोई आवश्यकता नहीं रखता है।

std::string निश्चित रूप से std::atomic<T> आवश्यकता है कि टेम्पलेट पैरामीटर T तुच्छता copyable हो, तो मानक स्थानों कार्यान्वयन पर कोई आवश्यकताओं को पूरा नहीं करता है। कार्यान्वयन के मुद्दे की गुणवत्ता के रूप में, ध्यान दें कि static_assert(std::is_trivially_copyable<T>::value, "std::atomic<T> requires T to be trivially copyable"); इस उल्लंघन को पकड़ने के लिए एक आसान निदान है।


2016-04-19 अपडेट: मैं जब परिवर्तन हुआ पता नहीं है, लेकिन VS2015 अद्यतन 2 अब std::atomic<std::string> का निदान करता है:

error C2338: atomic requires T to be trivially copyable.
0

तुम क्यों इस वसीयत में सोचते हैं std::atomic<std::string> पढ़ने/लिखने की कोशिश कर रहे कई थ्रेड हैं जब 'सही ढंग से' काम करते हैं?

यह सी ++ है, आपको निश्चित रूप से पैर में शूट करने की अनुमति है। यदि आप किसी ऐसे प्रकार का उपयोग करना चाहते हैं जो आप उपयोग करने के लिए स्वतंत्र हैं, तो संकलक "मई" (नहीं होगा!) आपको रोक देगा, लेकिन आप किसी बिंदु पर अजीब/अस्पष्ट व्यवहार देखना शुरू कर देंगे जब एकाधिक धागे पढ़ने की कोशिश करते हैं/स्ट्रिंग लिखें।

यह आवश्यकता पढ़ने और लिखने की परमाणुता की गारंटी के लिए है, यदि वस्तु छोटी संख्या में कॉपी करने योग्य नहीं है तो इस दृश्य को विज़ुअलाइज़ करें: स्ट्रिंग में "पुराना मान" था। 1 लेखक मुद्दे। स्टोर ("नया डेटा"), अब एक और धागा है जो एक ही चर पर .load() को जारी करता है, अब बिना trivially_copyable संपत्ति के, पाठक धागा "एनएलडी वैल्यू" या "न्यू वैल्यू" आदि देख सकता है। इसे परमाणु रूप से अद्यतन नहीं किया जा सकता है, इसलिए अजीब परिणाम।

चूंकि आपके द्वारा पोस्ट किया गया उदाहरण अनुक्रमिक कोड है, ऐसा नहीं होता है।

6

नहीं, यह अपरिभाषित व्यवहार है। इसके अलावा, के बाद से std :: स्ट्रिंग तुच्छता copyable नहीं है, अनुरूप संकलक जारी किए गए हैं चाहिए "कम से कम एक नैदानिक ​​message":

29,5 परमाणु प्रकार

वहाँ एक सामान्य वर्ग टेम्पलेट परमाणु है। टेम्पलेट तर्क टी का प्रकार तुच्छ रूप से कॉपी करने योग्य (3.9) होगा।

1.4 कार्यान्वयन अनुपालन

- एक कार्यक्रम किसी भी निदान नियम का उल्लंघन होता है, तो [...] एक अनुरूप कार्यान्वयन कम से कम एक नैदानिक ​​संदेश जारी करेगा।

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