2013-10-29 6 views
10

मैं एक atomic_flag का उपयोग कर एक स्पिन लॉक को लागू करने की कोशिश कर रहा हूँ। मुझे पता है कि सी ++ 11 के साथ मुझे atomic_flag चर शुरू करना है, लेकिन मैं इसे संकलित करने के लिए नहीं मिल सकता। मेरे कोड इस तरह दिखता है:) 'से पहले' { '':यदि मैं कक्षा के सदस्य हूं तो मैं एक परमाणु_फ्लैग चर कैसे प्रारंभ करूं?

class SpinLock 
{ 
public: 
    SpinLock() 
    :m_flag(ATOMIC_FLAG_INIT) /// syntax error : missing ')' before '{' 
    { 
    } 

    void lock() 
    { 
    while (m_flag.test_and_set() == true){} 
    } 

    void unlock() 
    { 
    m_flag.clear(); 
    } 

private: 
    SpinLock &operator=(const SpinLock &); 

private: 
    std::atomic_flag m_flag; 
}; 

जब मैं कोड संकलन मैं 'लापता सिंटेक्स त्रुटि' मिलता है। मैं यह भी देखता हूं कि ATOMIC_FLAG_INIT को {0} के रूप में परिभाषित किया गया है, लेकिन फिर इसे लिखने का सही तरीका क्या है?

निम्नलिखित संकलित करता है, लेकिन क्या यह अभी भी धागे सुरक्षित है?

SpinLock() 
    { 
     m_flag.clear(); 
    } 
+1

कौन सा संकलक आप उपयोग कर रहे हैं? आपके कोड को ठीक संकलित करना चाहिए। – inf

+1

यह एमएसवीसी 2013 आरसी और आरटीएम में संकलित नहीं है। (हालांकि यह पूर्वावलोकन में संकलित किया गया था)। मैंने http://connect.microsoft.com/VisualStudio/feedback/details/800243/visual-studio-2013-rc-std-atomic-flag-regression पर कनेक्ट बग दायर किया लेकिन वापस नहीं सुना है। इस बीच, मेरे कोड के लिए, मैंने std :: atomic का उपयोग किया है और एक्सचेंज (सत्य) के साथ test_and_set को प्रतिस्थापित किया है और स्टोर (झूठी) –

+0

के साथ साफ़ किया है, मैं विजुअल स्टूडियो 2012 –

उत्तर

11

Visual Studio 2012 ग का समर्थन नहीं करता ++ 11 प्रारंभकर्ता सूचियों (see the c++11 support page)

हालांकि यह विजुअल स्टूडियो 2013 में समर्थित है, (Uniform Initialization docs में "initializer_list कंस्ट्रक्टर्स" अनुभाग देखें)

इस बीच आपके मामले में निर्माता सिर्फ एक काम का उपयोग कर सकते m_flag = ATOMIC_FLAG_INIT;

अद्यतन: ऐसा लगता है कि यह उपर्युक्त असाइनमेंट का परीक्षण नहीं करता है, लेकिन m_flag.clear(); का उपयोग उसी परिणाम को प्राप्त करता है

+6

के लिए VS2012 का उपयोग करना होगा समस्या यह है कि 'atomic_flag' में कोई असाइनमेंट ऑपरेटर नहीं है, इसलिए कन्स्ट्रक्टर बॉडी में' ATOMIC_FLAG_INIT' के साथ ध्वज प्रारंभ करना संभव नहीं है। सही कन्स्ट्रक्टर का उपयोग करके ध्वज को प्रारंभ करना सही तरीका होगा (जो इसके राज्य को निर्दिष्ट नहीं करता है) और फिर राज्य को सेट करने के लिए '.clear()' पर कॉल करें। यह वास्तव में वीएस कार्यान्वयन की एक कष्टप्रद बग है। – ComicSansMS

+0

मैं इसे इस तरह से कोशिश कर रहा हूं, लेकिन यह सुनिश्चित नहीं है कि ध्वज प्रारंभिकता अभी भी थ्रेडसेफ –

+0

है क्योंकि आप अभी भी स्पिनलॉक कन्स्ट्रक्टर में हैं, फिर भी किसी अन्य थ्रेड को ध्वज तक पहुंच नहीं है क्योंकि आपकी ऑब्जेक्ट अभी तक मौजूद नहीं है "। –

1

यह वास्तव में एक बग (दृश्य 2013 आरटीएम) जैसा दिखता है। ATOMIC_FLAG_INIT कार्यान्वयन विशिष्ट है और {0} पर एक मैक्रो के रूप में हल करें। इसका मतलब है कि माइक्रोसॉफ्ट नौकरी करने के लिए कुल नियमों का उपयोग करता है।

उनके बारे में cppreference से उद्धरण: Until C++11, aggregate initialization could not be used in a constructor initializer list due to syntax restrictions.। मैंने निष्कर्ष निकाला है कि माइक्रोसॉफ्ट अभी तक इस व्यवहार को नहीं बदलता है।

यहाँ एक उदाहरण बजना पर ठीक काम कर रहा है और एक सरल मामले से VS2013 आरटीएम पर असफल रहने:

struct Pod { 
    int m_val; 
}; 

Pod g_1{ 0 }; // aggregate initialization 
Pod g_2{ { 0 } }; // just like ATOMIC_FLAG_INIT 

struct Foo { 
    Foo() : m_2 { 0 } {} // error C2664: 'Pod::Pod(const Pod &)' : cannot convert argument 1 from 'int' to 'const Pod &' 
    Pod m_1{ 0 }; // error C2664: 'Pod::Pod(const Pod &)' : cannot convert argument 1 from 'int' to 'const Pod &' 
    Pod m_2; // ok 
}; 
संबंधित मुद्दे

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