diff options
author | Matthew Newhook <matthew@zeroc.com> | 2006-03-02 08:48:09 +0000 |
---|---|---|
committer | Matthew Newhook <matthew@zeroc.com> | 2006-03-02 08:48:09 +0000 |
commit | 7da502a811dab261a851fca83545e64ceb985721 (patch) | |
tree | 06ca0aef3feeb3cfdc744acc2dd590b479d1237d /cppe/src | |
parent | requires STLport 5.0.2 (diff) | |
download | ice-7da502a811dab261a851fca83545e64ceb985721.tar.bz2 ice-7da502a811dab261a851fca83545e64ceb985721.tar.xz ice-7da502a811dab261a851fca83545e64ceb985721.zip |
http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=824
http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=725
http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=724
Diffstat (limited to 'cppe/src')
-rwxr-xr-x | cppe/src/IceE/Connection.cpp | 2 | ||||
-rw-r--r-- | cppe/src/IceE/RWRecMutex.cpp | 127 | ||||
-rw-r--r-- | cppe/src/IceE/Thread.cpp | 356 |
3 files changed, 210 insertions, 275 deletions
diff --git a/cppe/src/IceE/Connection.cpp b/cppe/src/IceE/Connection.cpp index f2878204a81..57058258ff9 100755 --- a/cppe/src/IceE/Connection.cpp +++ b/cppe/src/IceE/Connection.cpp @@ -178,7 +178,7 @@ Ice::Connection::isFinished() const if(_transceiver != 0 #ifndef ICEE_PURE_BLOCKING_CLIENT - || _dispatchCount != 0 || (_threadPerConnection && _threadPerConnection->getThreadControl().isAlive()) + || _dispatchCount != 0 || (_threadPerConnection && _threadPerConnection->isAlive()) #endif ) { diff --git a/cppe/src/IceE/RWRecMutex.cpp b/cppe/src/IceE/RWRecMutex.cpp index ed2caa767a4..52ef988db8e 100644 --- a/cppe/src/IceE/RWRecMutex.cpp +++ b/cppe/src/IceE/RWRecMutex.cpp @@ -11,11 +11,35 @@ #include <IceE/Exception.h> #include <IceE/Time.h> +IceUtil::DeadlockException::DeadlockException(const char* file, int line) : + Exception(file, line) +{ +} + +const char* IceUtil::DeadlockException::_name = "IceUtil::DeadlockException"; + +const ::std::string +IceUtil::DeadlockException::ice_name() const +{ + return _name; +} + +IceUtil::Exception* +IceUtil::DeadlockException::ice_clone() const +{ + return new DeadlockException(*this); +} + +void +IceUtil::DeadlockException::ice_throw() const +{ + throw *this; +} IceUtil::RWRecMutex::RWRecMutex() : _count(0), - _writerId(0), - _waitingWriters(0) + _waitingWriters(0), + _upgrading(false) { } @@ -95,7 +119,7 @@ IceUtil::RWRecMutex::writeLock() const // If the mutex is already write locked by this writer then // decrement _count, and return. // - if(_count < 0 && _writerId == ThreadControl().id()) + if(_count < 0 && _writerId == ThreadControl()) { --_count; return; @@ -107,7 +131,7 @@ IceUtil::RWRecMutex::writeLock() const // while(_count != 0) { - _waitingWriters++; + ++_waitingWriters; try { _writers.wait(lock); @@ -124,7 +148,7 @@ IceUtil::RWRecMutex::writeLock() const // Got the lock, indicate it's held by a writer. // _count = -1; - _writerId = ThreadControl().id(); + _writerId = ThreadControl(); } bool @@ -136,7 +160,7 @@ IceUtil::RWRecMutex::tryWriteLock() const // If the mutex is already write locked by this writer then // decrement _count, and return. // - if(_count < 0 && _writerId == ThreadControl().id()) + if(_count < 0 && _writerId == ThreadControl()) { --_count; return true; @@ -154,7 +178,7 @@ IceUtil::RWRecMutex::tryWriteLock() const // Got the lock, indicate it's held by a writer. // _count = -1; - _writerId = ThreadControl().id(); + _writerId = ThreadControl(); return true; } @@ -166,7 +190,7 @@ IceUtil::RWRecMutex::timedWriteLock(const Time& timeout) const // // If the mutex is already write locked by this writer then // decrement _count, and return. - if(_count < 0 && _writerId == ThreadControl().id()) + if(_count < 0 && _writerId == ThreadControl()) { --_count; return true; @@ -182,7 +206,7 @@ IceUtil::RWRecMutex::timedWriteLock(const Time& timeout) const Time remainder = end - Time::now(); if(remainder > Time()) { - _waitingWriters++; + ++_waitingWriters; try { bool result = _writers.timedWait(lock, remainder); @@ -208,7 +232,7 @@ IceUtil::RWRecMutex::timedWriteLock(const Time& timeout) const // Got the lock, indicate it's held by a writer. // _count = -1; - _writerId = ThreadControl().id(); + _writerId = ThreadControl(); return true; } @@ -258,7 +282,7 @@ IceUtil::RWRecMutex::unlock() const // ww = (_waitingWriters != 0 && _count == 0); wr = (_waitingWriters == 0); - } + } // Unlock mutex. // // Wake up a waiting writer if there is one. If not, wake up all @@ -266,14 +290,23 @@ IceUtil::RWRecMutex::unlock() const // if(ww) { - // - // Wake writer - // - _writers.signal(); + if(_upgrading) + { + // + // If there is an untimed upgrader, it runs. + // + _upgrader.signal(); + } + else + { + // + // Wake a normal writer. + // + _writers.signal(); + } } else if(wr) { - _writerId = 0; // // Wake readers // @@ -286,6 +319,11 @@ IceUtil::RWRecMutex::upgrade() const { Mutex::Lock lock(_mutex); + if(_upgrading) + { + throw DeadlockException(__FILE__, __LINE__); + } + // Reader owns at least one count // assert(_count > 0); @@ -294,27 +332,30 @@ IceUtil::RWRecMutex::upgrade() const // // Wait to acquire the write lock. // + _upgrading = true; while(_count != 0) { - _waitingWriters++; + ++_waitingWriters; try { - _writers.wait(lock); + _upgrader.wait(lock); } catch(...) { + _upgrading = false; --_waitingWriters; - _count++; + ++_count; throw; } - _waitingWriters--; + --_waitingWriters; } // // Got the lock, indicate it's held by a writer. // _count = -1; - _writerId = ThreadControl().id(); + _writerId = ThreadControl(); + _upgrading = false; } bool @@ -322,6 +363,15 @@ IceUtil::RWRecMutex::timedUpgrade(const Time& timeout) const { Mutex::Lock lock(_mutex); + // + // If another reader is already waiting for an upgrade, + // this upgrade cannot possibly succeed. + // + if(_upgrading) + { + return false; + } + // Reader owns at least one count // assert(_count > 0); @@ -330,35 +380,40 @@ IceUtil::RWRecMutex::timedUpgrade(const Time& timeout) const // // Wait to acquire the write lock. // + _upgrading = true; Time end = Time::now() + timeout; while(_count != 0) { Time remainder = end - Time::now(); if(remainder > Time()) { - _waitingWriters++; + ++_waitingWriters; try { - bool result = _writers.timedWait(lock, remainder); - _waitingWriters--; - if(result == false) + bool result = _upgrader.timedWait(lock, remainder); + --_waitingWriters; + if(!result) { - _count++; + _upgrading = false; + ++_count; return false; } } catch(...) { + _upgrading = false; --_waitingWriters; - _count++; + ++_count; throw; } } else { // - // If a timeout occurred then the lock wasn't acquired - _count++; + // The lock isn't acquired if a timeout occurred. + // + ++_count; + _upgrading = false; return false; } } @@ -367,6 +422,18 @@ IceUtil::RWRecMutex::timedUpgrade(const Time& timeout) const // Got the lock, indicate it's held by a writer. // _count = -1; - _writerId = ThreadControl().id(); + _writerId = ThreadControl(); + _upgrading = false; return true; } + +void +IceUtil::RWRecMutex::downgrade() const +{ + Mutex::Lock lock(_mutex); + + if(++_count == 0) + { + _count = 1; + } +} diff --git a/cppe/src/IceE/Thread.cpp b/cppe/src/IceE/Thread.cpp index d5cc992bd65..7869ec1583a 100644 --- a/cppe/src/IceE/Thread.cpp +++ b/cppe/src/IceE/Thread.cpp @@ -17,32 +17,53 @@ using namespace std; #ifdef _WIN32 -IceUtil::ThreadControl::ThreadControl() +#ifndef _WIN32_WCE +# include <process.h> +#endif + +#ifdef _WIN32_WCE +// +// Under WCE it is not possible to call DuplicateHandle on a thread +// handle. Instead we use the handle wrapper. This constructor uses +// GetCurrentThreadId() to get the current thread object. This object +// can also be used as the thread handle. +// +IceUtil::ThreadControl::ThreadControl() : + _id(GetCurrentThreadId()), + _handle(new HandleWrapper(static_cast<HANDLE>(_id), false)) { - IceUtil::Mutex::Lock lock(_stateMutex); - _handle = new HandleWrapper(GetCurrentThread(), false); - _id = GetCurrentThreadId(); } +#else +IceUtil::ThreadControl::ThreadControl() : + _id(GetCurrentThreadId()), + _handle(new HandleWrapper(0)) +{ + HANDLE currentThread = GetCurrentThread(); + HANDLE currentProcess = GetCurrentProcess(); + + if(DuplicateHandle(currentProcess, + currentThread, + currentProcess, + &_handle->handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS) == 0) + { + throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); + } +} +#endif -IceUtil::ThreadControl::ThreadControl(const HandleWrapperPtr& handle, ThreadId id) +IceUtil::ThreadControl::ThreadControl(const HandleWrapperPtr& handle, IceUtil::ThreadControl::ID id) : + _id(id), + _handle(handle) { - IceUtil::Mutex::Lock lock(_stateMutex); - _handle = handle; - _id = id; } -IceUtil::ThreadControl::ThreadControl(const ThreadControl& tc) +IceUtil::ThreadControl::ThreadControl(const ThreadControl& tc) : + _id(tc.id), + _handle(tc.handle) { - ThreadId id; - HandleWrapperPtr handle; - { - IceUtil::Mutex::Lock lock(tc._stateMutex); - id = tc._id; - handle = tc._handle; - } - IceUtil::Mutex::Lock lock(_stateMutex); - _handle = handle; - _id = id; } IceUtil::ThreadControl& @@ -50,16 +71,8 @@ IceUtil::ThreadControl::operator=(const ThreadControl& rhs) { if(&rhs != this) { - ThreadId id; - HandleWrapperPtr handle; - { - IceUtil::Mutex::Lock lock(rhs._stateMutex); - handle = rhs._handle; - id = rhs._id; - } - IceUtil::Mutex::Lock lock(_stateMutex); - _handle = handle; - _id = id; + _id = rhs.id; + _handle = rhs.handle; } return *this; } @@ -67,41 +80,19 @@ IceUtil::ThreadControl::operator=(const ThreadControl& rhs) bool IceUtil::ThreadControl::operator==(const ThreadControl& rhs) const { - ThreadId id = rhs.id(); - IceUtil::Mutex::Lock lock(_stateMutex); - return _id == id; + return _id == rhs._id; } bool IceUtil::ThreadControl::operator!=(const ThreadControl& rhs) const { - return !operator==(rhs); -} - -bool -IceUtil::ThreadControl::operator<(const ThreadControl& rhs) const -{ - ThreadId id = rhs.id(); - IceUtil::Mutex::Lock lock(_stateMutex); - return _id < id; -} - -IceUtil::ThreadId -IceUtil::ThreadControl::id() const -{ - IceUtil::Mutex::Lock lock(_stateMutex); - return _id; + return _id != rhs._id; } void IceUtil::ThreadControl::join() { - HandleWrapperPtr handle; - { - IceUtil::Mutex::Lock lock(_stateMutex); - handle = _handle; - } - int rc = WaitForSingleObject(handle->handle, INFINITE); + int rc = WaitForSingleObject(_handle->handle, INFINITE); if(rc != WAIT_OBJECT_0) { throw ThreadSyscallException(__FILE__, __LINE__, GetLastError()); @@ -114,27 +105,16 @@ IceUtil::ThreadControl::detach() // No-op: Windows doesn't have the concept of detaching a thread. } -bool -IceUtil::ThreadControl::isAlive() const +IceUtil::ThreadControl::ID +IceUtil::ThreadControl::id() const { - HandleWrapperPtr handle; - { - IceUtil::Mutex::Lock lock(_stateMutex); - handle = _handle; - } - DWORD rc; - if(GetExitCodeThread(handle->handle, &rc) == 0) - { - return false; - } - return rc == STILL_ACTIVE; + return _id; } void IceUtil::ThreadControl::sleep(const Time& timeout) { - long msec = (long)timeout.toMilliSeconds(); - Sleep(msec); + Sleep(static_cast<long>(timeout.toMilliSeconds())); } void @@ -148,29 +128,18 @@ IceUtil::ThreadControl::yield() Sleep(0); } -IceUtil::Thread::Thread() +IceUtil::Thread::Thread() : + _started(false), + _running(false), + _handle(new HandleWrapper(0)), + _id(0) { - IceUtil::Mutex::Lock lock(_stateMutex); - _started = false; - _id = 0; - _handle = new HandleWrapper(0); } IceUtil::Thread::~Thread() { } -IceUtil::ThreadId -IceUtil::Thread::id() const -{ - IceUtil::Mutex::Lock lock(_stateMutex); - if(!_started) - { - throw ThreadNotStartedException(__FILE__, __LINE__); - } - return _id; -} - static void* startHook(void* arg) { @@ -200,13 +169,11 @@ startHook(void* arg) { fprintf(stderr, "IceUtil::Thread::run(): uncaught exception: %s\n", e.toString()); } + thread->_done(); + return 0; } -#ifndef _WIN32_WCE -#include <process.h> -#endif - IceUtil::ThreadControl IceUtil::Thread::start(size_t stackSize) { @@ -247,6 +214,7 @@ IceUtil::Thread::start(size_t stackSize) } _started = true; + _running = true; return ThreadControl(_handle, _id); } @@ -265,25 +233,7 @@ IceUtil::Thread::getThreadControl() const bool IceUtil::Thread::operator==(const Thread& rhs) const { - // - // Get rhs ID. - // - ThreadId id = rhs.id(); - - // - // Check that this thread was started. - // - IceUtil::Mutex::Lock lock(_stateMutex); - if(!_started) - { - throw ThreadNotStartedException(__FILE__, __LINE__); - } - - // - // We perform the comparison within the scope of the lock, otherwise the hardware has no - // way of knowing that it might have to flush a cache line. - // - return _id == id; + return this == &rhs; } bool @@ -295,46 +245,38 @@ IceUtil::Thread::operator!=(const Thread& rhs) const bool IceUtil::Thread::operator<(const Thread& rhs) const { - // - // Get rhs ID. - // - ThreadId id = rhs.id(); + return this < &rhs; +} - // - // Check that this thread was started. - // +bool +IceUtil::Thread::isAlive() const +{ IceUtil::Mutex::Lock lock(_stateMutex); - if(!_started) - { - throw ThreadNotStartedException(__FILE__, __LINE__); - } + return _running; +} - // - // We perform the comparison within the scope of the lock, otherwise the hardware has no - // way of knowing that it might have to flush a cache line. - // - return _id < id; +void +IceUtil::Thread::_done() +{ + IceUtil::Mutex::Lock lock(_stateMutex); + _running = false; } #else -IceUtil::ThreadControl::ThreadControl(ThreadId id) +IceUtil::ThreadControl::ThreadControl(pthread_t thread) : + _thread(thread) { - IceUtil::Mutex::Lock lock(_stateMutex); - _id = id; } -IceUtil::ThreadControl::ThreadControl() +IceUtil::ThreadControl::ThreadControl() : + _thread(pthread_self()) { - IceUtil::Mutex::Lock lock(_stateMutex); - _id = pthread_self(); } -IceUtil::ThreadControl::ThreadControl(const ThreadControl& tc) +IceUtil::ThreadControl::ThreadControl(const ThreadControl& tc) : + _thread(tc._thread) { - ThreadId id = tc.id(); - IceUtil::Mutex::Lock lock(_stateMutex); - _id = id; } IceUtil::ThreadControl& @@ -342,9 +284,7 @@ IceUtil::ThreadControl::operator=(const ThreadControl& rhs) { if(&rhs != this) { - ThreadId id = rhs.id(); - IceUtil::Mutex::Lock lock(_stateMutex); - _id = id; + _thread = rhs._thread; } return *this; } @@ -352,9 +292,7 @@ IceUtil::ThreadControl::operator=(const ThreadControl& rhs) bool IceUtil::ThreadControl::operator==(const ThreadControl& rhs) const { - ThreadId id = rhs.id(); - IceUtil::Mutex::Lock lock(_stateMutex); - return pthread_equal(_id, id); + return pthread_equal(_thread, rhs._thread) != 0; } bool @@ -363,32 +301,11 @@ IceUtil::ThreadControl::operator!=(const ThreadControl& rhs) const return !operator==(rhs); } -bool -IceUtil::ThreadControl::operator<(const ThreadControl& rhs) const -{ - ThreadId id = rhs.id(); - IceUtil::Mutex::Lock lock(_stateMutex); - // NOTE: Linux specific - return _id < id; -} - -IceUtil::ThreadId -IceUtil::ThreadControl::id() const -{ - IceUtil::Mutex::Lock lock(_stateMutex); - return _id; -} - void IceUtil::ThreadControl::join() { - ThreadId id; - { - IceUtil::Mutex::Lock lock(_stateMutex); - id = _id; - } void* ignore = 0; - int rc = pthread_join(id, &ignore); + int rc = pthread_join(_thread, &ignore); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); @@ -398,34 +315,17 @@ IceUtil::ThreadControl::join() void IceUtil::ThreadControl::detach() { - ThreadId id; - { - IceUtil::Mutex::Lock lock(_stateMutex); - id = _id; - } - int rc = pthread_detach(id); + int rc = pthread_detach(_thread); if(rc != 0) { throw ThreadSyscallException(__FILE__, __LINE__, rc); } } -bool -IceUtil::ThreadControl::isAlive() const +IceUtil::ThreadControl::ID +IceUtil::ThreadControl::id() const { - int policy; - int ret; - struct sched_param param; - IceUtil::Mutex::Lock lock(_stateMutex); - - ret = pthread_getschedparam(_id, &policy, ¶m); -#ifdef __APPLE__ - if (ret == 0) - { - ret = pthread_setschedparam(_id, policy, ¶m); - } -#endif - return (ret == 0); + return _thread; } void @@ -444,41 +344,30 @@ IceUtil::ThreadControl::yield() sched_yield(); } -IceUtil::Thread::Thread() +IceUtil::Thread::Thread() : + _started(false), + _running(false) { - IceUtil::Mutex::Lock lock(_stateMutex); - _started = false; - _id = 0; } IceUtil::Thread::~Thread() { } -IceUtil::ThreadId -IceUtil::Thread::id() const -{ - IceUtil::Mutex::Lock lock(_stateMutex); - if(!_started) - { - throw ThreadNotStartedException(__FILE__, __LINE__); - } - return _id; -} - extern "C" { static void* startHook(void* arg) { + // + // Ensure that the thread doesn't go away until run() has + // completed. + // + IceUtil::ThreadPtr thread; try { IceUtil::Thread* rawThread = static_cast<IceUtil::Thread*>(arg); - // - // Ensure that the thread doesn't go away until run() has - // completed. - // - IceUtil::ThreadPtr thread = rawThread; + thread = rawThread; // // See the comment in IceUtil::Thread::start() for details. @@ -494,6 +383,8 @@ startHook(void* arg) { fprintf(stderr, "IceUtil::Thread::run(): uncaught exception\n"); } + thread->_done(); + return 0; } } @@ -539,7 +430,7 @@ IceUtil::Thread::start(size_t stackSize) __decRef(); throw ThreadSyscallException(__FILE__, __LINE__, rc); } - rc = pthread_create(&_id, &attr, startHook, this); + rc = pthread_create(&_thread, &attr, startHook, this); if(rc != 0) { __decRef(); @@ -548,7 +439,7 @@ IceUtil::Thread::start(size_t stackSize) } else { - int rc = pthread_create(&_id, 0, startHook, this); + int rc = pthread_create(&_thread, 0, startHook, this); if(rc != 0) { __decRef(); @@ -557,8 +448,9 @@ IceUtil::Thread::start(size_t stackSize) } _started = true; + _running = true; - return ThreadControl(_id); + return ThreadControl(_thread); } IceUtil::ThreadControl @@ -569,31 +461,13 @@ IceUtil::Thread::getThreadControl() const { throw ThreadNotStartedException(__FILE__, __LINE__); } - return ThreadControl(_id); + return ThreadControl(_thread); } bool IceUtil::Thread::operator==(const Thread& rhs) const { - // - // Get rhs ID. - // - ThreadId id = rhs.id(); - - // - // Check that this thread was started. - // - IceUtil::Mutex::Lock lock(_stateMutex); - if(!_started) - { - throw ThreadNotStartedException(__FILE__, __LINE__); - } - - // - // We perform the comparison within the scope of the lock, otherwise the hardware has no - // way of knowing that it might have to flush a cache line. - // - return pthread_equal(_id, id); + return this == &rhs; } bool @@ -605,27 +479,21 @@ IceUtil::Thread::operator!=(const Thread& rhs) const bool IceUtil::Thread::operator<(const Thread& rhs) const { - // - // Get rhs ID. - // - ThreadId id = rhs.id(); + return this < &rhs; +} - // - // Check that this thread was started. - // +bool +IceUtil::Thread::isAlive() const +{ IceUtil::Mutex::Lock lock(_stateMutex); - if(!_started) - { - throw ThreadNotStartedException(__FILE__, __LINE__); - } + return _running; +} - // - // We perform the comparison within the scope of the lock, otherwise the hardware has no - // way of knowing that it might have to flush a cache line. - // - // NOTE: Linux specific - // - return _id < id; +void +IceUtil::Thread::_done() +{ + IceUtil::Mutex::Lock lock(_stateMutex); + _running = false; } #endif |