// ********************************************************************** // // Copyright (c) 2000 // Object Oriented Concepts, Inc. // Billerica, MA, USA // // All Rights Reserved // // ********************************************************************** #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_STRSTREAM) # include #else # if defined(HAVE_STRSTREA_H) # include # else # include # endif #endif #ifdef HAVE_STD_IOSTREAM using namespace std; #endif #include // // Inlining the methods causes problems with CC 7.1 under SGI // #if defined(__sgi) JTCSynchronized::JTCSynchronized(const JTCMonitor& mon) : mon_(&mon), lockType_(LOCKED_MONITOR) { mon_ -> lock(false); } JTCSynchronized::JTCSynchronized(const JTCMonitor& mon, bool internal) : mon_(&mon), lockType_(LOCKED_MONITOR) { mon_ -> lock(internal); } JTCSynchronized::JTCSynchronized(const JTCMutex& m) : mut_(&m), lockType_(LOCKED_MUTEX) { mut_ -> lock(); } JTCSynchronized::JTCSynchronized(const JTCRecursiveMutex& m) : nrmut_(&m), lockType_(LOCKED_RECURSIVE_MUTEX) { nrmut_ -> lock(); } JTCSynchronized::~JTCSynchronized() { switch(lockType_) { case LOCKED_MONITOR: mon_ -> unlock(); break; case LOCKED_MUTEX: mut_ -> unlock(); break; case LOCKED_RECURSIVE_MUTEX: nrmut_ -> unlock(); break; } } #endif // ---------------------------------------------------------------------- // JTCMonitor private member implementation // ---------------------------------------------------------------------- // // Verify that the mutex is locked by the calling thread. If the mutex // is not locked by the calling thread then throw // JTCIllegalMonitorStateException. // void JTCMonitor::validateMutexOwner(const char* caller) const { if(monMutex_._JTC_getId() != JTCThreadId::self()) { char buf[1024]; ostrstream os(buf, 1024); os << "JTCMonitor::" << caller << " Thread: " << JTCThreadId::self() << " doesn't own mutex. Owner: " << monMutex_._JTC_getId() << ends; throw JTCIllegalMonitorStateException(buf); } } // // Lock the monitors mutex. If internal is set then do not check the // running status of the current thread. // void JTCMonitor::lock(bool internal) const { #ifdef HAVE_JTC_STOP if (!internal) { JTCThread::_JTC_checkRunningStatus(); } ((JTCMonitor*)this) -> internalLock_ = internal; #endif monMutex_.lock(); } // // Unlock the monitors mutex. If this was a lock placed by an internal // method of the JTC library then do not check the current threads // running status. // void JTCMonitor::unlock() const { #ifdef HAVE_JTC_STOP bool internalLock = internalLock_; monMutex_.unlock(); if (!internalLock) { JTCThread::_JTC_checkRunningStatus(); } #else monMutex_.unlock(); #endif } // ---------------------------------------------------------------------- // JTCMonitor constructor and destructor // ---------------------------------------------------------------------- JTCMonitor::JTCMonitor() : monCond_(monMutex_) #ifdef HAVE_JTC_STOP , internalLock_(false) #endif { } JTCMonitor::~JTCMonitor() { } // ---------------------------------------------------------------------- // JTCMonitor public member implementation // ---------------------------------------------------------------------- // // Wait for the monitor to be signalled. // void JTCMonitor::wait() { #ifdef HAVE_JTC_STOP // // Check the threads running status. // JTCThread::_JTC_checkRunningStatus(); // // Verify that the monitor is locked by the calling thread. // validateMutexOwner("wait"); // // Tell the current thread that it is waiting in a monitor. // JTCThread::_JTC_setMonitor(this); try { monCond_.wait(); } catch(...) { // // The current thread is no longer in a monitor. Check the // running status. // JTCThread::_JTC_setMonitor(0); JTCThread::_JTC_checkRunningStatus(); throw; } // // The current thread is no longer in a monitor. Check the running // status. // JTCThread::_JTC_setMonitor(0); JTCThread::_JTC_checkRunningStatus(); #else // // Verify that the monitor is locked by the calling thread. // validateMutexOwner("wait(long)"); monCond_.wait(); #endif } // // Wait to be signalled for timeout milliseconds. // void JTCMonitor::wait(long timeout) { #ifdef HAVE_JTC_STOP // // Check the threads running status. // JTCThread::_JTC_checkRunningStatus(); // // Verify that the monitor is locked by the calling thread. // validateMutexOwner("wait(long)"); // // Tell the current thread that it is waiting in a monitor. // JTCThread::_JTC_setMonitor(this); try { monCond_.wait(timeout); } catch(...) { // // The current thread is no longer in a monitor. Check the // running status. // JTCThread::_JTC_setMonitor(0); JTCThread::_JTC_checkRunningStatus(); throw; } // // The current thread is no longer in a monitor. Check the running // status. // // JTCThread::_JTC_setMonitor(0); JTCThread::_JTC_checkRunningStatus(); #else // // Verify that the monitor is locked by the calling thread. // validateMutexOwner("wait(long)"); monCond_.wait(timeout); #endif } // // Wake one waiting thread. // void JTCMonitor::notify() { // // Ensure that the monitors mutex is locked by the calling thread. // validateMutexOwner("notify"); monCond_.signal(); } // // Wake all waiting threads. // void JTCMonitor::notifyAll() { // // Ensure that the monitors mutex is locked by the calling thread. // validateMutexOwner("notifyAll"); monCond_.broadcast(); }