2013-04-01 10 views
35

Chcę użyć std::atomic_bool, ponieważ chcę mieć boolean, który ma być dostępny przez różne wątki.Inicjalizacja std :: atomic_bool?

Jest to zmienna członkowska static. Problem polega na tym, że chcę go zainicjować przy pomocy false jako pierwszego stanu. Zwykle zrobiłbym to tak: std::atomic_bool World::mStopEvent = false;

Ale problem wydaje się, że nie bierze false jako konstruktora. Więc jak mam zainicjować taką zmienną? używam VS 2012.

Odpowiedz

36

To known issue in Visual Studio 2012 (known as VC11) należy głosować na istniejącym sprzęcie Połącz więc, że Microsoft wie, że wpływa więcej ludzi jak oni odroczone poprawki.

Hi,

Thanks for reporting this bug. I'm Microsoft's maintainer of the STL, and I wanted to let you know that while this bug remains active in our database, it won't be fixed in VC11 RTM (VS 2012 RTM). All bugs are important to us, but some are more severe than others and rise to the top of our priority queue.

I'm copying-and-pasting this response across all of the STL's active Connect bugs, but the following terse comments apply specifically to your bug:

  • Yep, we're missing these constructors on atomic_bool , atomic_int , etc. (atomic<bool> , atomic<int> , etc. have them). 29.5 [atomics.types.generic]/7 says "There shall be named types corresponding to the integral specializations of atomic, as specified in Table 145, and a named type atomic_bool corresponding to the specified atomic<bool> . Each named type is a either typedef to the corresponding specialization or a base class of the corresponding specialization. If it is a base class, it shall support the same member functions as the corresponding specialization." which makes me really want to use typedefs (1 type is always simpler than 2 types), but I'll need to see if that would introduce any other issues.

I can't promise when we'll be able to resolve this bug, but we hope to do so as soon as possible (and I'll send another response when that happens) - our first opportunity will be the "out of band" release between VC11 and VC12 that Herb Sutter announced at the GoingNative 2012 conference.

Note: Connect doesn't notify me about comments. If you have any further questions, please E-mail me.

Stephan T. Lavavej Senior Developer - Visual C++ Libraries [email protected]

Na razie musisz teraz użyć numeru std::atomic<T>.

2

Jak o:

std::atomic_bool World::mStopEvent(false); 
+3

sam błąd: 'error C2440: 'inicjowanie': nie można przekonwertować z ' bool 'na' std :: atomic_bool ' 1> Żaden konstruktor nie może przyjąć typu źródłowego lub rozdzielczość przeciążania konstruktora była niejednoznaczna' – Sapd

20

PROBLEM:

Nie można używać kopiowania inicjalizację, ponieważ std::atomic_bool nie jest kopia constructible:

std::atomic_bool World::mStopEvent = false; // ERROR! 

W rzeczywistości, powyższe jest równoważne:

std::atomic_bool World::mStopEvent = std::atomic_bool(false); // ERROR! 

Można jednak użyć bezpośrednio-inicjowania zacji:

std::atomic_bool World::mStopEvent(false); 

Na Państwa życzenie, można wybrać zamiast wykorzystywać szelki z nawiasami:

std::atomic_bool World::mStopEvent{false}; 

BUG:

Podczas kopiowania inicjalizacji jest nielegalne bez względu na to, co kompilator wybierz, wydaje się, że implementacja Standardowej Biblioteki dostarczonej z VC11 ma błąd, który nie pozwoli ci na bezpośrednią inicjalizację.

So how I am supposed to initialize such a variable?

Obejście:

W celu obejścia tego problemu można podać parę statycznych owijarki że getter/setter - odpowiednio - ustawienie i powrócić wartość atomowej flagi wartości logicznej, ale nie przed dokonaniem upewnić się, że została zainicjowana przynajmniej raz i nie więcej niż raz do żądanej wartości początkowej w sposób bezpieczny wątku (można rozważyć to jakiś leniwej inicjalizacji):

#include <atomic> 
#include <mutex> 

struct World 
{ 
    static bool is_stop_event_set() 
    { 
     std::call_once(mStopEventInitFlag, []() { mStopEvent = false; }); 
     return mStopEvent; 
    } 

    static void set_stop_event(bool value) 
    { 
     std::call_once(mStopEventInitFlag, [value]() { mStopEvent = value; }); 
     mStopEvent = value; 
    } 

    static std::atomic_bool mStopEvent; 
    static std::once_flag mStopEventInitFlag; 
}; 

std::atomic_bool World::mStopEvent; 
std::once_flag World::mStopEventInitFlag; 

teraz zamiast dostępie mStopEvent bezpośrednio, jego wartość powinna być odczytywana przez is_stop_event_set() funkcję:

#include <iostream> 

int main() 
{ 
    std::cout << World::is_stop_event_set(); // Will return false 
} 
+0

Tak, inicjowanie bezpośrednie też nie działa :( – Sapd

+1

@Sapd: Próbowałem zapewnić obejście problemu, mam nadzieję, że pomaga –

+0

Tak, dziękuję, chciałem mimo wszystko użyć akcesorów. Szkoda, że ​​to obciążenie jest potrzebne. – Sapd

16

Spróbuj tego:

atomic_bool my_bool = ATOMIC_VAR_INIT(false); 

http://en.cppreference.com/w/cpp/atomic/ATOMIC_VAR_INIT

+1

Myślę, że to najlepsza odpowiedź tutaj, ponieważ rozwiązuje problem w najkrótszy i bez obciążenia. Również to rozwiązanie jest crossplatform, skompilowałem go w VS i Xcode. – GuidC0DE

+0

Tak, kompiluje się z Clang na Mac OS X, ale z ostrzeżeniem "nawiasami wokół inicjalizatora skalarnego [-Wbraced-scalar-init]". Oczywiście, jeśli ją włączyłeś. – dismine