diff options
Diffstat (limited to 'cpp/src/IceUtil/RecMutex.cpp')
-rw-r--r-- | cpp/src/IceUtil/RecMutex.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/cpp/src/IceUtil/RecMutex.cpp b/cpp/src/IceUtil/RecMutex.cpp new file mode 100644 index 00000000000..91735b00c78 --- /dev/null +++ b/cpp/src/IceUtil/RecMutex.cpp @@ -0,0 +1,168 @@ +// ********************************************************************** +// +// Copyright (c) 2001 +// MutableRealms, Inc. +// Huntsville, AL, USA +// +// All Rights Reserved +// +// ********************************************************************** + +#include <IceUtil/RecMutex.h> +#include <IceUtil/Exception.h> + +using namespace std; + +#ifdef WIN32 + +IceUtil::RecMutex::RecMutex() : + _count(0) +{ + InitializeCriticalSection(&_mutex); +} + +IceUtil::RecMutex::~RecMutex() +{ + assert(_count == 0); + DeleteCriticalSection(&_mutex); +} + +bool +IceUtil::RecMutex::lock() +{ + EnterCriticalSection(&_mutex); + if (++_count > 1) + { + LeaveCriticalSection(&_mutex); + return false; + } + return true; +} + +bool +IceUtil::RecMutex::trylock() +{ + if (!TryEnterCriticalSection(&_mutex)) + { + throw LockedException(__FILE__, __LINE__); + } + if (++_count > 1) + { + LeaveCriticalSection(&_mutex); + return false; + } + return true; +} + +bool +IceUtil::RecMutex::unlock() +{ + if (--_count == 0) + { + LeaveCriticalSection(&_mutex); + return true; + } + return false; +} + +void +IceUtil::RecMutex::unlock(LockState& state) +{ + state.count = _count; + _count = 0; + LeaveCriticalSection(&_mutex); +} + +void +IceUtil::RecMutex::lock(LockState& state) +{ + EnterCriticalSection(&_mutex); + _count = state.count; +} +#else + +IceUtil::RecMutex::RecMutex() : + _count(0) +{ + const pthread_mutexattr_t attr = { PTHREAD_MUTEX_RECURSIVE_NP }; + int rc = pthread_mutex_init(&_mutex, &attr); + if (rc != 0) + { + throw SyscallException(strerror(rc), __FILE__, __LINE__); + } +} + +IceUtil::RecMutex::~RecMutex() +{ + assert(_count == 0); + int rc = 0; + rc = pthread_mutex_destroy(&_mutex); + assert(rc == 0); +} + +bool +IceUtil::RecMutex::lock() +{ + int rc = pthread_mutex_lock(&_mutex); + if (rc != 0) + { + throw SyscallException(strerror(rc), __FILE__, __LINE__); + } + if (++_count > 1) + { + rc = pthread_mutex_unlock(&_mutex); + assert(rc == 0); + return false; + } + return true; +} + +bool +IceUtil::RecMutex::trylock() +{ + int rc = pthread_mutex_trylock(&_mutex); + if (rc != 0) + { + if (rc == EBUSY) + { + throw LockedException(__FILE__, __LINE__); + } + throw SyscallException(strerror(rc), __FILE__, __LINE__); + } + if (++_count > 1) + { + rc = pthread_mutex_unlock(&_mutex); + assert(rc == 0); + return false; + } + return true; +} + +bool +IceUtil::RecMutex::unlock() +{ + if (--_count == 0) + { + int rc = 0; // Prevent warnings when NDEBUG is defined. + rc = pthread_mutex_unlock(&_mutex); + assert(rc == 0); + return true; + } + return false; +} + +void +IceUtil::RecMutex::unlock(LockState& state) +{ + state.mutex = &_mutex; + state.count = _count; + _count = 0; +} + +void +IceUtil::RecMutex::lock(LockState& state) +{ + _count = state.count; +} + +#endif |