1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/base/StaticMutex.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,90 @@ 1.4 +#ifndef mozilla_StaticMutex_h 1.5 +#define mozilla_StaticMutex_h 1.6 + 1.7 +#include "mozilla/Atomics.h" 1.8 +#include "mozilla/Mutex.h" 1.9 + 1.10 +namespace mozilla { 1.11 + 1.12 +/** 1.13 + * StaticMutex is a Mutex that can (and in fact, must) be used as a 1.14 + * global/static variable. 1.15 + * 1.16 + * The main reason to use StaticMutex as opposed to 1.17 + * StaticAutoPtr<OffTheBooksMutex> is that we instantiate the StaticMutex in a 1.18 + * thread-safe manner the first time it's used. 1.19 + * 1.20 + * The same caveats that apply to StaticAutoPtr apply to StaticMutex. In 1.21 + * particular, do not use StaticMutex as a stack variable or a class instance 1.22 + * variable, because this class relies on the fact that global variablies are 1.23 + * initialized to 0 in order to initialize mMutex. It is only safe to use 1.24 + * StaticMutex as a global or static variable. 1.25 + */ 1.26 +class StaticMutex 1.27 +{ 1.28 +public: 1.29 + // In debug builds, check that mMutex is initialized for us as we expect by 1.30 + // the compiler. In non-debug builds, don't declare a constructor so that 1.31 + // the compiler can see that the constructor is trivial. 1.32 +#ifdef DEBUG 1.33 + StaticMutex() 1.34 + { 1.35 + MOZ_ASSERT(!mMutex); 1.36 + } 1.37 +#endif 1.38 + 1.39 + void Lock() 1.40 + { 1.41 + Mutex()->Lock(); 1.42 + } 1.43 + 1.44 + void Unlock() 1.45 + { 1.46 + Mutex()->Unlock(); 1.47 + } 1.48 + 1.49 + void AssertCurrentThreadOwns() 1.50 + { 1.51 +#ifdef DEBUG 1.52 + Mutex()->AssertCurrentThreadOwns(); 1.53 +#endif 1.54 + } 1.55 + 1.56 +private: 1.57 + OffTheBooksMutex* Mutex() 1.58 + { 1.59 + if (mMutex) { 1.60 + return mMutex; 1.61 + } 1.62 + 1.63 + OffTheBooksMutex* mutex = new OffTheBooksMutex("StaticMutex"); 1.64 + if (!mMutex.compareExchange(nullptr, mutex)) { 1.65 + delete mutex; 1.66 + } 1.67 + 1.68 + return mMutex; 1.69 + } 1.70 + 1.71 + Atomic<OffTheBooksMutex*> mMutex; 1.72 + 1.73 + 1.74 + // Disallow copy constructor, but only in debug mode. We only define 1.75 + // a default constructor in debug mode (see above); if we declared 1.76 + // this constructor always, the compiler wouldn't generate a trivial 1.77 + // default constructor for us in non-debug mode. 1.78 +#ifdef DEBUG 1.79 + StaticMutex(StaticMutex &other); 1.80 +#endif 1.81 + 1.82 + // Disallow these operators. 1.83 + StaticMutex& operator=(StaticMutex* rhs); 1.84 + static void* operator new(size_t) CPP_THROW_NEW; 1.85 + static void operator delete(void*); 1.86 +}; 1.87 + 1.88 +typedef BaseAutoLock<StaticMutex> StaticMutexAutoLock; 1.89 +typedef BaseAutoUnlock<StaticMutex> StaticMutexAutoUnlock; 1.90 + 1.91 +} // namespace mozilla 1.92 + 1.93 +#endif