diff options
Diffstat (limited to 'cppe/src/IceE/RecMutex.cpp')
-rw-r--r-- | cppe/src/IceE/RecMutex.cpp | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/cppe/src/IceE/RecMutex.cpp b/cppe/src/IceE/RecMutex.cpp new file mode 100644 index 00000000000..9137d232aae --- /dev/null +++ b/cppe/src/IceE/RecMutex.cpp @@ -0,0 +1,309 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICEE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceE/RecMutex.h> +#include <IceE/Exception.h> + +using namespace std; + +#ifdef _WIN32 + +# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 + +IceE::RecMutex::RecMutex() : + _count(0) +{ + InitializeCriticalSection(&_mutex); +} + +IceE::RecMutex::~RecMutex() +{ + assert(_count == 0); + DeleteCriticalSection(&_mutex); +} + +void +IceE::RecMutex::lock() const +{ + EnterCriticalSection(&_mutex); + if(++_count > 1) + { + LeaveCriticalSection(&_mutex); + } +} + +bool +IceE::RecMutex::tryLock() const +{ + if(!TryEnterCriticalSection(&_mutex)) + { + return false; + } + if(++_count > 1) + { + LeaveCriticalSection(&_mutex); + } + return true; +} + +void +IceE::RecMutex::unlock() const +{ + if(--_count == 0) + { + LeaveCriticalSection(&_mutex); + } +} + +void +IceE::RecMutex::unlock(LockState& state) const +{ + state.count = _count; + _count = 0; + LeaveCriticalSection(&_mutex); +} + +void +IceE::RecMutex::lock(LockState& state) const +{ + EnterCriticalSection(&_mutex); + _count = state.count; +} + +# else + +IceE::RecMutex::RecMutex() : + _count(0) +{ + _mutex = CreateMutex(0, false, 0); + if(_mutex == 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } +} + +IceE::RecMutex::~RecMutex() +{ + assert(_count == 0); + BOOL rc = CloseHandle(_mutex); + if(rc == 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } +} + +void +IceE::RecMutex::lock() const +{ + DWORD rc = WaitForSingleObject(_mutex, INFINITE); + if(rc != WAIT_OBJECT_0) + { + if(rc == WAIT_FAILED) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } + else + { + throw ThreadSyscallException(__FILE__, __LINE__, 0); + } + } + + if(++_count > 1) + { + BOOL rc2 = ReleaseMutex(_mutex); + if(rc2 == 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } + } +} + +bool +IceE::RecMutex::tryLock() const +{ + DWORD rc = WaitForSingleObject(_mutex, 0); + if(rc != WAIT_OBJECT_0) + { + return false; + } + if(++_count > 1) + { + BOOL rc2 = ReleaseMutex(_mutex); + if(rc2 == 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } + } + return true; +} + +void +IceE::RecMutex::unlock() const +{ + if(--_count == 0) + { + BOOL rc = ReleaseMutex(_mutex); + if(rc == 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } + } +} + +void +IceE::RecMutex::unlock(LockState& state) const +{ + state.count = _count; + _count = 0; + BOOL rc = ReleaseMutex(_mutex); + if(rc == 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } +} + +void +IceE::RecMutex::lock(LockState& state) const +{ + DWORD rc = WaitForSingleObject(_mutex, INFINITE); + if(rc != WAIT_OBJECT_0) + { + if(rc == WAIT_FAILED) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } + else + { + throw ThreadSyscallException(__FILE__, __LINE__, 0); + } + } + + _count = state.count; +} + +# endif + +#else + +IceE::RecMutex::RecMutex() : + _count(0) +{ + int rc; + +#if defined(__linux) && !defined(__USE_UNIX98) + const pthread_mutexattr_t attr = { PTHREAD_MUTEX_RECURSIVE_NP }; +#else + pthread_mutexattr_t attr; + rc = pthread_mutexattr_init(&attr); + if(rc != 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, rc); + } + rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if(rc != 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, rc); + } +#endif + + rc = pthread_mutex_init(&_mutex, &attr); + if(rc != 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, rc); + } + +#if defined(__linux) && !defined(__USE_UNIX98) +// Nothing to do +#else + rc = pthread_mutexattr_destroy(&attr); + if(rc != 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, rc); + } +#endif +} + +IceE::RecMutex::~RecMutex() +{ + assert(_count == 0); + int rc = 0; + rc = pthread_mutex_destroy(&_mutex); + assert(rc == 0); +} + +void +IceE::RecMutex::lock() const +{ + int rc = pthread_mutex_lock(&_mutex); + if(rc != 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, rc); + } + if(++_count > 1) + { + rc = pthread_mutex_unlock(&_mutex); + assert(rc == 0); + } +} + +bool +IceE::RecMutex::tryLock() const +{ + int rc = pthread_mutex_trylock(&_mutex); + bool result = (rc == 0); + if(!result) + { + if(rc != EBUSY) + { + throw ThreadSyscallException(__FILE__, __LINE__, rc); + } + } + else if(++_count > 1) + { + rc = pthread_mutex_unlock(&_mutex); + if(rc != 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, rc); + } + } + return result; +} + +void +IceE::RecMutex::unlock() const +{ + if(--_count == 0) + { + int rc = 0; // Prevent warnings when NDEBUG is defined. + rc = pthread_mutex_unlock(&_mutex); + assert(rc == 0); + } +} + +void +IceE::RecMutex::unlock(LockState& state) const +{ + state.mutex = &_mutex; + state.count = _count; + _count = 0; +} + +void +IceE::RecMutex::lock(LockState& state) const +{ + _count = state.count; +} + +#endif + +bool +IceE::RecMutex::willUnlock() const +{ + return _count == 1; +} |