summaryrefslogtreecommitdiff
path: root/cppe/src
diff options
context:
space:
mode:
authorMatthew Newhook <matthew@zeroc.com>2006-03-02 08:48:09 +0000
committerMatthew Newhook <matthew@zeroc.com>2006-03-02 08:48:09 +0000
commit7da502a811dab261a851fca83545e64ceb985721 (patch)
tree06ca0aef3feeb3cfdc744acc2dd590b479d1237d /cppe/src
parentrequires STLport 5.0.2 (diff)
downloadice-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-xcppe/src/IceE/Connection.cpp2
-rw-r--r--cppe/src/IceE/RWRecMutex.cpp127
-rw-r--r--cppe/src/IceE/Thread.cpp356
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, &param);
-#ifdef __APPLE__
- if (ret == 0)
- {
- ret = pthread_setschedparam(_id, policy, &param);
- }
-#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