2013-10-29 14 views
10

Bir atomic_flag kullanarak bir döndürme kilidi uygulamaya çalışıyorum. C++ 11 ile atomic_flag değişkenini başlatmam gerektiğini biliyorum, ancak derlemeyi başaramıyorum. Benim kod şöyle görünür:) 'önce '{' ': Ben kod derleme yaparkenBir atomic_flag değişkenini bir sınıfın üyesiyse nasıl başlatırım?

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; 
}; 

Ben' eksik sözdizimi hatası' olsun. Ayrıca ATOMIC_FLAG_INIT'in {0} olarak tanımlandığını görüyorum, ancak bunu yazmanın doğru yolu nedir?

Aşağıdakiler derler, ancak hala iş parçacığı güvenli midir?

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

kullandığınız hangi derleyici? Kodunuz iyi bir şekilde derlenmeli. – inf

+1

Bu, MSVC 2013 RC ve RTM'de derlenmez. (Ancak Önizleme'de derlemişti). Http://connect.microsoft.com/VisualStudio/feedback/details/800243/visual-studio-2013-rc-std-atomic-flag-regression adresinden bir bağlantı hatası gönderdim, ancak geri dönüşü duymadım. Bu arada, kodum için std :: atomic 'u kullandım ve test_and_set'i exchange (true) ile değiştirdim ve store (false) ile temizle –

+0

Görsel stüdyo kullanıyorum 2012 –

cevap

11

Visual Studio 2012 Ancak Visual Studio 2013 desteklenir

,

( Uniform Initialization docs yılında "initializer_list Yapıcılar" bölümüne bakınız) C++ 11 başlatıcı listelerini ( see the c++11 support page)

desteklemiyor

arada sizin durumunuzda yapıcı sadece atama kullanabilirsiniz m_flag = ATOMIC_FLAG_INIT;

Güncelleme: Yukarıdaki ödevi test etmemiş gibi görünüyor, ancak m_flag.clear(); kullanarak aynı sonucu elde ediyor

+6

Sorun şu ki, atomic_flag'ın hiçbir atama operatörü yoktur, bu yüzden kurucunun gövdesinde "ATOMIC_FLAG_INIT" ile bayrağı başlatmak mümkün değildir. Doğru yol, varsayılan yapıcıyı (bu, durumunu belirtilmemiş olan) bırakarak başlatmak ve sonra durumu ayarlamak için '.clear()' ı çağırmaktır. Bu gerçekten VS uygulamasının sinir bozucu bir hatasıdır. – ComicSansMS

+0

Bu şekilde deniyorum, ancak bayrak başlatma işleminin hala threadafe olup olmadığından emin değilsiniz –

+0

Hala SpinLock yapıcısında olduğunuzdan, başka bir iş parçacığı, henüz "henüz mevcut değil" olduğundan, bayrağıma erişemedi. –

1

Gerçekten bir hataya benziyor (visual 2013 rtm). ATOMIC_FLAG_INIT uygulaması, uygulamaya özeldir ve {0} için bir makro olarak çözülür. Bu, Microsoft'un işi yapmak için bir araya getirilmiş kurallar kullandığı anlamına gelir.

Bunlardan cppreference alıntı: Until C++11, aggregate initialization could not be used in a constructor initializer list due to syntax restrictions.. Microsoft'un bu davranışı henüz değiştirmediği sonucuna varıyorum.

İşte bir exemple clang üzerinde iyi çalışıyor ve daha basit bir vaka ile VS2013 RTM üzerinde başarısız:

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 
}; 
İlgili konular