diff options
author | Bernard Normier <bernard@zeroc.com> | 2005-04-14 15:49:51 +0000 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2005-04-14 15:49:51 +0000 |
commit | be347a7c38f42b6c00d90ac536bd0ce8253a225d (patch) | |
tree | bcbcdf01659d7f6da1c584adbfb9347bc30fc85f /cpp/src/IceUtil/StaticMutex.cpp | |
parent | Removed more stuff (diff) | |
download | ice-be347a7c38f42b6c00d90ac536bd0ce8253a225d.tar.bz2 ice-be347a7c38f42b6c00d90ac536bd0ce8253a225d.tar.xz ice-be347a7c38f42b6c00d90ac536bd0ce8253a225d.zip |
Improved Double-Check Locking with memory barriers
(InterlockedCompareExchangePointer)
Diffstat (limited to 'cpp/src/IceUtil/StaticMutex.cpp')
-rw-r--r-- | cpp/src/IceUtil/StaticMutex.cpp | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/cpp/src/IceUtil/StaticMutex.cpp b/cpp/src/IceUtil/StaticMutex.cpp index bb8c2f37c7d..0dea0acddc2 100644 --- a/cpp/src/IceUtil/StaticMutex.cpp +++ b/cpp/src/IceUtil/StaticMutex.cpp @@ -48,7 +48,6 @@ static Init _init; Init::Init() { InitializeCriticalSection(&_criticalSection); - _mutexList = new MutexList; } @@ -70,35 +69,43 @@ Init::~Init() } } -// -// For full thread-safety, we assume that _mutexInitialized cannot be seen as true -// before CRITICAL_SECTION has been updated. This is true on x86. Does IA64 -// provide the same memory ordering guarantees? -// - void IceUtil::StaticMutex::initialize() const { + // + // Yes, a double-check locking. It should be safe since we use memory barriers + // (through InterlockedCompareExchangePointer) in both reader and writer threads + // EnterCriticalSection(&_criticalSection); - if(!_mutexInitialized) + + // + // The second check + // + if(_mutex == 0) { # if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 - _mutex = new CRITICAL_SECTION; - InitializeCriticalSection(_mutex); - _mutexList->push_back(_mutex); + CRITICAL_SECTION* newMutex = new CRITICAL_SECTION; + InitializeCriticalSection(newMutex); # else _recursionCount = 0; - _mutex = CreateMutex(0, false, 0); - if(_mutex == 0) + + HANDLE newMutex = CreateMutex(0, false, 0); + if(newMutex == 0) { + LeaveCriticalSection(&_criticalSection); throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); } - _mutexList->push_back(_mutex); # endif - _mutexInitialized = true; + + // + // _mutex is written after the new initialized CRITICAL_SECTION/Mutex + // + void* oldVal = InterlockedCompareExchangePointer(reinterpret_cast<void**>(&_mutex), newMutex, 0); + assert(oldVal == 0); + _mutexList->push_back(_mutex); + } LeaveCriticalSection(&_criticalSection); } - #endif IceUtil::StaticMutex IceUtil::globalMutex = ICE_STATIC_MUTEX_INITIALIZER; |