zamrate wrote:Could you maybe give an example when using a normal CriticalSection as static variable would not work? I've done that quite a lot in my code, but never have had any problems (until now!).
Two cases:
1) CriticalSection at function scope with static storage duration. Example:
- Code: Select all
void calledFromMultipleThreads ()
{
static CriticalSection mutex;
// Race condition causes double initializion with some build environments
CriticalSection::ScopedLockType lock (mutex);
}
2) CriticalSection at file scope with static storage duration, accessed from a constructor of an object at file scope with static storage duration. Example:
- Code: Select all
//foo.cpp
CriticalSection globalMutex;
//bar.cpp
extern CriticalSection globalMutex;
struct Singleton {
Singleton ()
{
CriticalSection::ScopedLockType lock (globalMutex);
// Will fail if we execute before globalLock constructor
}
};
Singleton globalSingleton; // Will fail depending on order of constructors
StaticCriticalSection solves both cases. In c++0x condition #1 is fixed (but #2 is still a problem).
- Code: Select all
namespace { struct PrivateTag { }; } // distinguishes the StaticCriticalSection
void safelyCalledFromMultipleThreads ()
{
StaticCriticalSection <PrivateTag> mutex;
StaticCriticalSection <PrivateTag>::ScopedLockType lock (mutex);
// Works correctly when called from multiple threads
}
and
- Code: Select all
//common.h
struct GlobalMutexTag { };
//foo.cpp
StaticCriticalSection <GlobalMutexTag> globalMutex;
//bar.cpp
extern StaticCriticalSection <GlobalMutexTag> globalMutex;
struct Singleton
{
Singleton ()
{
StaticCriticalSection <GlobalMutexTag>::ScopedLockType lock (globalMutex);
// Works no matter what the order of construction
}
};
Singleton globalSingleton; // Always constructs properly no matter what the order