Wir haben ein interessantes C++ Problem mit scoped static variables.
Zuerst einmal: wir nutzen Visual Studio 2013 ohne November CTP (dieses macht nämlich an anderer Stelle Probleme), weswegen scoped static initialization nicht threadsafe ist.
Insbesondere ist folgender Code eine Race Condition (die uns auch tatsächlich in der Anwendung diverse non-deterministische Access Violations liefert):
(Der Code wird natürlich aus diversen Thread parallel aufgerufen)
Code: Alles auswählen
foo()
{
static A* a = bar();
... a nutzen
}
(Unter gcc und clang ist natürlich alles ok, die implementieren das threadsafe init von C++11 bereits korrekt)
Da nach der ersten Initialisierung kaum noch Aufwand auf diese Codestelle entfällt, kam mir die Idee, ein Spinlock zum sichern zu nehmen:
Code: Alles auswählen
static std::atomic_flag lock = ATOMIC_FLAG_INIT; // non-function scope
foo()
{
while (lock.test_and_set(std::memory_order_acquire)) { } // spin
static A* a = bar();
lock.clear(std::memory_order_release);
... a nutzen
}
Insbesondere ist das für unser Macro dann sehr unangenehm, außerhalb der Funktionen noch die Locks zu erstellen.
Allerdings ist ATOMIC_FLAG_INIT ein #define auf {0} und so wie die Implementierung von atomic_flag im VS 13 aussieht, müsste das astreine zero-initialization sein.
Jetzt die Frage: kann man vll doch einfach threadsafe static den lock zero-initialisieren und dann als spinlock verwenden?
Oder offener: hat jemand eine bessere Idee mit dem Problem umzugehen?