// ********************************************************************** // // Copyright (c) 2000 // Object Oriented Concepts, Inc. // Billerica, MA, USA // // All Rights Reserved // // ********************************************************************** #include #include #include #include #include #include #include #ifdef HAVE_STD_IOSTREAM using namespace std; #endif // ---------------------------------------------------------------------- // JTCRecursiveMutex private member implementation // ---------------------------------------------------------------------- void JTCRecursiveMutex::lockI(int count) { // // This flag is set to true once the mutex has been obtained. // bool ob = false; while(!ob) { // // Lock the internal mutex. // internal_.lock(); // // count_ represents the number of times the mutex has been // aquired. If count_ is zero then the mutex is not yet // aquired. Note that two mutexes cannot be in here at once, // since this CS is protected by the mutex internal_. // if(!count_) { // // We're attempting to aquire the mutex count more times. // count_ = count; owner_ = JTCThreadId::self(); ob = true; // // Acquire the mutexes critical section. // try { #if defined(HAVE_POSIX_THREADS) || defined(HAVE_DCE_THREADS) JTC_SYSCALL_1(pthread_mutex_lock, &crit_, != 0) #endif #if defined(HAVE_WIN32_THREADS) EnterCriticalSection(&crit_); #endif } catch(...) { try { internal_.unlock(); } catch(...) { } throw; } } // // Otherwise count_ is non-zero. This means that the mutex is // currently aquired. There are two cases here: // // - The mutex is owned by the caller. Simply increment the // count in this case. // // - The mutex is owned by a thread other than the caller. In // this case we attempt to aquire the mutexes critical // section. This CS is unlocked once mutex is released count_ // times. // else if(owner_ == JTCThreadId::self()) { count_ += count; ob = true; } internal_.unlock(); // // If we haven't yet obtained the mutex lock the critical // section mutex. Immediately unlock the CS, then attempt to // re-obtain. // if(!ob) { #if defined(HAVE_POSIX_THREADS) || defined(HAVE_DCE_THREADS) JTC_SYSCALL_1(pthread_mutex_lock, &crit_, != 0) pthread_mutex_unlock(&crit_); #endif #if defined(HAVE_WIN32_THREADS) EnterCriticalSection(&crit_); LeaveCriticalSection(&crit_); #endif } } } void JTCRecursiveMutex::unlockI() { // // Aquire the internal mutex. // internal_.lock(); // // If count_ decrements to zero then unlock the mutexes CS. The // mutex is no longer owned by a thread. // if(--count_ == 0) { owner_ = JTCThreadId(); #if defined(HAVE_POSIX_THREADS) || defined(HAVE_DCE_THREADS) pthread_mutex_unlock(&crit_); #endif #if defined(HAVE_WIN32_THREADS) LeaveCriticalSection(&crit_); #endif } internal_.unlock(); } // // Lock the mutex count times. // void JTCRecursiveMutex::lock(int count) const { // // Work around lack of mutable. // ((JTCRecursiveMutex*)this) -> lockI(count); } // ---------------------------------------------------------------------- // JTCRecursiveMutex constructor and destructor // ---------------------------------------------------------------------- JTCRecursiveMutex::JTCRecursiveMutex() : count_(0), owner_(JTCThreadId()) { #if defined(HAVE_POSIX_THREADS) JTC_SYSCALL_2(pthread_mutex_init, &crit_, 0, != 0) #endif #if defined(HAVE_DCE_THREADS) JTC_SYSCALL_2(pthread_mutex_init, &crit_, pthread_mutexattr_default, != 0) #endif #if defined(HAVE_WIN32_THREADS) InitializeCriticalSection(&crit_); #endif } JTCRecursiveMutex::~JTCRecursiveMutex() { #if defined(HAVE_POSIX_THREADS) || defined(HAVE_DCE_THREADS) pthread_mutex_destroy(&crit_); #endif #if defined(HAVE_WIN32_THREADS) DeleteCriticalSection(&crit_); #endif } // ---------------------------------------------------------------------- // JTCRecursiveMutex public member implementation // ---------------------------------------------------------------------- // // Lock the mutex. // void JTCRecursiveMutex::lock() const { // // Work around lack of mutable. // ((JTCRecursiveMutex*)this) -> lockI(1); } // // Unlock the mutex. // void JTCRecursiveMutex::unlock() const { // // Work around lack of mutable. // ((JTCRecursiveMutex*)this) -> unlockI(); } // // Return the ID of the owning thread. If the mutex isn't locked then // return nullThreadId. // JTCThreadId JTCRecursiveMutex::_JTC_getId() const { JTCRecursiveMutex* This = (JTCRecursiveMutex*)this; // // Aquire the internal mutex. // This -> internal_.lock(); JTCThreadId id; if(count_ > 0) id = owner_; This -> internal_.unlock(); return id; }