diff options
author | Dwayne Boone <dwayne@zeroc.com> | 2005-07-05 11:09:55 +0000 |
---|---|---|
committer | Dwayne Boone <dwayne@zeroc.com> | 2005-07-05 11:09:55 +0000 |
commit | 9b8cc712d4a41d71840416776bc94ee8485bb9b3 (patch) | |
tree | 7d467fdd6a66bc2b5878d82070d45adbd5c20414 /cppe/test/IceE/thread/RWRecMutexTest.cpp | |
parent | cleaning the cache method out of ReferenceFactory (diff) | |
download | ice-9b8cc712d4a41d71840416776bc94ee8485bb9b3.tar.bz2 ice-9b8cc712d4a41d71840416776bc94ee8485bb9b3.tar.xz ice-9b8cc712d4a41d71840416776bc94ee8485bb9b3.zip |
Changed Ice to IceE EVERYWHERE!!!
Diffstat (limited to 'cppe/test/IceE/thread/RWRecMutexTest.cpp')
-rw-r--r-- | cppe/test/IceE/thread/RWRecMutexTest.cpp | 543 |
1 files changed, 543 insertions, 0 deletions
diff --git a/cppe/test/IceE/thread/RWRecMutexTest.cpp b/cppe/test/IceE/thread/RWRecMutexTest.cpp new file mode 100644 index 00000000000..22dc2e612e4 --- /dev/null +++ b/cppe/test/IceE/thread/RWRecMutexTest.cpp @@ -0,0 +1,543 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of IceE is licensed to you under the terms described in the +// ICEE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceE/IceE.h> +#include <IceE/RWRecMutex.h> + +#include <RWRecMutexTest.h> +#include <TestCommon.h> + +using namespace std; +using namespace IceE; + +static const std::string rwRecMutexTestName("read/write recursive mutex"); + +class RWRecMutexTestThread : public Thread +{ +public: + + RWRecMutexTestThread(RWRecMutex& m) : + _mutex(m), + _tryLock(false) + { + } + + void + waitTryLock() + { + Mutex::Lock lock(_tryLockMutex); + while(!_tryLock) + { + _tryLockCond.wait(lock); + } + } + +protected: + + RWRecMutex& _mutex; + bool _tryLock; + + // + // Use native Condition variable here, not Monitor. + // + Cond _tryLockCond; + Mutex _tryLockMutex; +}; + +class RWRecMutexReadTestThread : public RWRecMutexTestThread +{ +public: + + RWRecMutexReadTestThread(RWRecMutex& m) : + RWRecMutexTestThread(m) + { + } + + virtual void + run() + { + RWRecMutex::TryRLock tlock(_mutex); + test(tlock.acquired()); + + { + Mutex::Lock lock(_tryLockMutex); + _tryLock = true; + } + _tryLockCond.signal(); + + RWRecMutex::RLock lock(_mutex); + } +}; + +class RWRecMutexReadTestThread2 : public RWRecMutexTestThread +{ +public: + + RWRecMutexReadTestThread2(RWRecMutex& m) : + RWRecMutexTestThread(m) + { + } + + virtual void + run() + { + + RWRecMutex::TryRLock tlock(_mutex); + test(!tlock.acquired()); + + { + Mutex::Lock lock(_tryLockMutex); + _tryLock = true; + } + _tryLockCond.signal(); + + RWRecMutex::RLock lock(_mutex); + } +}; + +class RWRecMutexUpgradeReadThread : public Thread +{ +public: + + RWRecMutexUpgradeReadThread(RWRecMutex& m) : + _mutex(m), + _unlock(false), + _lock(false) + { + } + virtual void + run() + { + RWRecMutex::RLock lock(_mutex); + + signalLock(); + waitUnlock(); + } + + void + waitUnlock() + { + Mutex::Lock lock(_unlockMutex); + while(!_unlock) + { + _unlockCond.wait(lock); + } + } + + void + signalUnlock() + { + Mutex::Lock lock(_unlockMutex); + _unlock = true; + _unlockCond.signal(); + } + + void + signalLock() + { + Mutex::Lock lock(_lockMutex); + _lock = true; + _lockCond.signal(); + } + + void + waitLock() + { + Mutex::Lock lock(_lockMutex); + while(!_lock) + { + _lockCond.wait(lock); + } + } + +private: + + RWRecMutex& _mutex; + + // + // Use native Condition variable here, not Monitor. + // + Cond _unlockCond; + Mutex _unlockMutex; + bool _unlock; + + Cond _lockCond; + Mutex _lockMutex; + bool _lock; +}; +typedef Handle<RWRecMutexUpgradeReadThread> RWRecMutexUpgradeReadThreadPtr; + +class RWRecMutexUpgradeTestThread : public Thread +{ +public: + + RWRecMutexUpgradeTestThread(RWRecMutex& m) : + _mutex(m), + _lock(false), + _upgradeAcquired(false) + { + } + + virtual void + run() + { + RWRecMutex::RLock lock(_mutex); + + signalLock(); + lock.upgrade(); + + _upgradeAcquired = true; + } + + void + signalLock() + { + Mutex::Lock lock(_lockMutex); + _lock = true; + _lockCond.signal(); + } + + void + waitLock() + { + Mutex::Lock lock(_lockMutex); + while(!_lock) + { + _lockCond.wait(lock); + } + } + + bool + upgradeAcquired() const + { + return _upgradeAcquired; + } + +private: + + RWRecMutex& _mutex; + + // + // Use native Condition variable here, not Monitor. + // + Cond _lockCond; + Mutex _lockMutex; + bool _lock; + + bool _upgradeAcquired; +}; +typedef Handle<RWRecMutexUpgradeTestThread> RWRecMutexUpgradeTestThreadPtr; + +class RWRecMutexWriteTestThread : public RWRecMutexTestThread +{ +public: + + RWRecMutexWriteTestThread(RWRecMutex& m) : + RWRecMutexTestThread(m) + { + } + + virtual void + run() + { + + RWRecMutex::TryWLock tlock(_mutex); + test(!tlock.acquired()); + + { + Mutex::Lock lock(_tryLockMutex); + _tryLock = true; + } + _tryLockCond.signal(); + + RWRecMutex::WLock lock(_mutex); + } +}; +typedef Handle<RWRecMutexTestThread> RWRecMutexTestThreadPtr; + +RWRecMutexTest::RWRecMutexTest() : + TestBase(rwRecMutexTestName) +{ +} + +void +RWRecMutexTest::run() +{ + RWRecMutex mutex; + RWRecMutexTestThreadPtr t; + ThreadControl control; + + // TEST: TryLock (read) + { + RWRecMutex::RLock rlock(mutex); + + // RLock testing + test(rlock.acquired()); + + try + { + rlock.acquire(); + test(false); + } + catch(const ThreadLockedException&) + { + // Expected + } + + try + { + rlock.tryAcquire(); + test(false); + } + catch(const ThreadLockedException&) + { + // Expected + } + + test(rlock.acquired()); + rlock.release(); + test(!rlock.acquired()); + + try + { + rlock.release(); + test(false); + } + catch(const ThreadLockedException&) + { + // Expected + } + + test(rlock.tryAcquire() == true); + test(rlock.acquired()); + + RWRecMutex::RLock rlock2(mutex); + + RWRecMutex::TryRLock trlock(mutex); + test(trlock.acquired()); + + RWRecMutex::TryWLock twlock(mutex); + test(!twlock.acquired()); + + RWRecMutex::TryWLock twlock2(mutex, Time::milliSeconds(10)); + test(!twlock2.acquired()); + } + + // TEST: TryLock (write) + { + RWRecMutex::WLock wlock(mutex); + + // WLock testing + test(wlock.acquired()); + + try + { + wlock.acquire(); + test(false); + } + catch(const ThreadLockedException&) + { + // Expected + } + + try + { + wlock.tryAcquire(); + test(false); + } + catch(const ThreadLockedException&) + { + // Expected + } + + test(wlock.acquired()); + wlock.release(); + test(!wlock.acquired()); + + try + { + wlock.release(); + test(false); + } + catch(const ThreadLockedException&) + { + // Expected + } + + test(wlock.tryAcquire() == true); + test(wlock.acquired()); + + RWRecMutex::TryRLock trlock(mutex); + test(!trlock.acquired()); + + RWRecMutex::TryRLock trlock2(mutex, Time::milliSeconds(10)); + test(!trlock2.acquired()); + + RWRecMutex::TryWLock twlock(mutex); + test(twlock.acquired()); + + RWRecMutex::TryWLock twlock2(mutex, Time::milliSeconds(10)); + test(twlock2.acquired()); + } + + // TEST: read lock + { + RWRecMutex::RLock rlock(mutex); + + // TEST: Start thread, try to acquire the mutex. + t = new RWRecMutexReadTestThread(mutex); + control = t->start(); + + // TEST: Wait until the tryLock has been tested. + t->waitTryLock(); + } + + // + // TEST: Once the mutex has been released, the thread should + // acquire the mutex and then terminate. + // + control.join(); + + // TEST: write lock + { + RWRecMutex::WLock wlock(mutex); + + // TEST: Start thread, try to acquire the mutex. + t = new RWRecMutexWriteTestThread(mutex); + control = t->start(); + + // TEST: Wait until the tryLock has been tested. + t->waitTryLock(); + } + + // + // TEST: Once the mutex has been released, the thread should + // acquire the mutex and then terminate. + // + control.join(); + + // TEST: Lock precedence. Writers have precedence over readers. + { + RWRecMutex::RLock rlock(mutex); + + // Start thread that tries to acquire write lock + t = new RWRecMutexWriteTestThread(mutex); + control = t->start(); + + // TEST: Wait until the tryLock has been tested. The thread is + // now waiting on a write lock. + t->waitTryLock(); + + // It's necessary for a small sleep here to ensure that the + // thread is actually waiting on a write lock. + ThreadControl::sleep(Time::seconds(1)); + + RWRecMutex::TryRLock trlock(mutex); + test(!trlock.acquired()); + } + + // + // TEST: Once the mutex has been released, the thread should + // acquire the mutex and then terminate. + // + control.join(); + + // TEST: Lock upgrading. + { + RWRecMutex::RLock rlock(mutex); + + // + // Mutex now holds a write lock. + // + mutex.upgrade(); + + // Start thread that tries to acquire write lock + t = new RWRecMutexReadTestThread2(mutex); + control = t->start(); + + // TEST: Wait until the tryLock has been tested. The thread is + // now waiting on a read lock. + t->waitTryLock(); + + // It's necessary for a small sleep here to ensure that the + // thread is actually waiting on a read lock. + ThreadControl::sleep(Time::seconds(1)); + } + + // + // TEST: Once the mutex has been released, the thread should + // acquire the mutex and then terminate. + // + control.join(); + + // + // COMPILERBUG: Under Linux with gcc this causes the Mutex test to + // fail for some unknown reason. After spending more than enough + // time looking into this problem it was decided that this is a + // compiler bug of some sort. + // +#if !(defined(__linux) && defined(__GNUC__)) + // TEST: Lock upgrading. This time a reader thread is started + // first. + { + RWRecMutexUpgradeReadThreadPtr t1 = new RWRecMutexUpgradeReadThread(mutex); + control = t1->start(); + + // Wait for the thread to acquire the read lock. + t1->waitLock(); + + // Spawn a thread to try acquiring the lock + RWRecMutexUpgradeTestThreadPtr t2 = new RWRecMutexUpgradeTestThread(mutex); + ThreadControl control2 = t2->start(); + t2->waitLock(); + + // + // Small sleep to find out whether the thread actually + // terminates (which means that the write lock upgrade was + // mistakenly acquired). + // + ThreadControl::sleep(Time::seconds(1)); + + test(!t2->upgradeAcquired()); + + // + // A read lock at this point should fail. + // + + RWRecMutex::TryRLock trlock(mutex); + test(!trlock.acquired()); + + // + // As should a write lock. + // + + RWRecMutex::TryWLock twlock(mutex); + test(!twlock.acquired()); + + // + // Once the read lock is released then the upgrade should + // succeed & the thread should terminate. + // + t1->signalUnlock(); + + control2.join(); + control.join(); + + // + // Now both a read & write lock should be available. + // + { + RWRecMutex::WLock rlock2(mutex); + } + { + RWRecMutex::RLock rlock2(mutex); + } + } +#endif +} |