summaryrefslogtreecommitdiff
path: root/cpp/test/IceUtil/thread/RWRecMutexTest.cpp
diff options
context:
space:
mode:
authorMatthew Newhook <matthew@zeroc.com>2005-10-27 05:33:05 +0000
committerMatthew Newhook <matthew@zeroc.com>2005-10-27 05:33:05 +0000
commit8b60a5994e0678a202bc695a7ea181b7822f1f71 (patch)
tree66c516b2f263defbdfc6a6c7b8f8d61280681e71 /cpp/test/IceUtil/thread/RWRecMutexTest.cpp
parentfixed substitute buttons (diff)
downloadice-8b60a5994e0678a202bc695a7ea181b7822f1f71.tar.bz2
ice-8b60a5994e0678a202bc695a7ea181b7822f1f71.tar.xz
ice-8b60a5994e0678a202bc695a7ea181b7822f1f71.zip
http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=547
Diffstat (limited to 'cpp/test/IceUtil/thread/RWRecMutexTest.cpp')
-rw-r--r--cpp/test/IceUtil/thread/RWRecMutexTest.cpp342
1 files changed, 201 insertions, 141 deletions
diff --git a/cpp/test/IceUtil/thread/RWRecMutexTest.cpp b/cpp/test/IceUtil/thread/RWRecMutexTest.cpp
index 71071d01bd4..c34f1153b42 100644
--- a/cpp/test/IceUtil/thread/RWRecMutexTest.cpp
+++ b/cpp/test/IceUtil/thread/RWRecMutexTest.cpp
@@ -260,171 +260,217 @@ public:
};
typedef Handle<RWRecMutexTestThread> RWRecMutexTestThreadPtr;
-RWRecMutexTest::RWRecMutexTest() :
- TestBase(rwRecMutexTestName)
-{
-}
-
-class UpgradeThread : public RWRecMutexTestThread
+class RWRecMutexUpgradeThread : public Thread, public IceUtil::Monitor<IceUtil::Mutex>
{
public:
- UpgradeThread(RWRecMutex& m, int initialDelay, int upgradeDelay, int writeHoldTime, int readHoldTime)
- : RWRecMutexTestThread(m),
- _initialDelay(upgradeDelay),
- _upgradeDelay(upgradeDelay),
- _writeHoldTime(writeHoldTime),
- _readHoldTime(readHoldTime),
- _deadlock(false),
- _hasUpgrade(false)
+ RWRecMutexUpgradeThread(RWRecMutex& m, bool timed = false)
+ : _m(m),
+ _timed(timed),
+ _destroyed(false),
+ _upgrading(false),
+ _hasLock(false),
+ _failed(false)
{
}
virtual void
run()
{
- ThreadControl::sleep(Time::seconds(_initialDelay));
- _mutex.readLock();
+ //
+ // Acquire a read lock.
+ //
+ RWRecMutex::TryRLock tlock(_m);
+
+ {
+ Lock sync(*this);
+ _upgrading = true;
+ notify();
+ }
try
{
- ThreadControl::sleep(Time::seconds(_upgradeDelay));
- _mutex.upgrade();
- _hasUpgrade = true;
+ if(_timed)
+ {
+ if(!_m.timedUpgrade(IceUtil::Time::seconds(10)))
+ {
+ _failed = true;
+ }
+ }
+ else
+ {
+ _m.upgrade();
+ }
}
- catch(const DeadlockException&)
+ catch(DeadlockException& ex)
{
- _deadlock = true;
+ _failed = true;
}
- if(!_deadlock)
{
- ThreadControl::sleep(Time::seconds(_writeHoldTime));
- _mutex.downgrade();
- _hasUpgrade = false;
+ Lock sync(*this);
+ _hasLock = true;
+ notify();
+
+ while(!_destroyed)
+ {
+ wait();
+ }
}
+ }
+
+ void
+ waitUpgrade()
+ {
+ Lock sync(*this);
- ThreadControl::sleep(Time::seconds(_readHoldTime));
- _mutex.unlock();
+ //
+ // Wait for the _upgrading flag to be set.
+ //
+ while(!_upgrading)
+ {
+ wait();
+ }
+
+ //
+ // Its necessary to sleep for 1 second to ensure that the
+ // thread is actually IN the upgrade and waiting.
+ //
+ ThreadControl::sleep(Time::seconds(1));
+ }
+
+ void
+ destroy()
+ {
+ Lock sync(*this);
+ _destroyed = true;
+ notify();
}
bool
- deadlock()
+ waitHasLock()
{
- return _deadlock;
+ Lock sync(*this);
+ if(!_hasLock)
+ {
+ timedWait(Time::seconds(1));
+ }
+ return _hasLock;
}
bool
- hasUpgrade()
+ failed() const
{
- return _hasUpgrade;
+ return _failed;
}
private:
- int _initialDelay;
- int _upgradeDelay;
- int _writeHoldTime;
- int _readHoldTime;
- bool _deadlock;
- bool _hasUpgrade;
+ RWRecMutex& _m;
+ bool _timed;
+ bool _destroyed;
+ bool _upgrading;
+ bool _hasLock;
+ bool _failed;
};
-typedef Handle<UpgradeThread> UpgradeThreadPtr;
+typedef Handle<RWRecMutexUpgradeThread> RWRecMutexUpgradeThreadPtr;
-class TimedUpgradeThread : public RWRecMutexTestThread
+class RWRecMutexWriteThread : public Thread, public IceUtil::Monitor<IceUtil::Mutex>
{
public:
- TimedUpgradeThread(RWRecMutex& m, int waitTime,
- int initialDelay, int upgradeDelay, int writeHoldTime, int readHoldTime)
- : RWRecMutexTestThread(m),
- _waitTime(waitTime),
- _initialDelay(upgradeDelay),
- _upgradeDelay(upgradeDelay),
- _writeHoldTime(writeHoldTime),
- _readHoldTime(readHoldTime),
- _upgradeSucceeded(false)
+ RWRecMutexWriteThread(RWRecMutex& m)
+ : _m(m),
+ _destroyed(false),
+ _waitWrite(false),
+ _hasLock(false)
{
}
virtual void
run()
{
- ThreadControl::sleep(Time::seconds(_initialDelay));
- _mutex.readLock();
-
- ThreadControl::sleep(Time::seconds(_upgradeDelay));
- _upgradeSucceeded = _mutex.timedUpgrade(Time::seconds(_waitTime));
-
- if(_upgradeSucceeded)
{
- ThreadControl::sleep(Time::seconds(_writeHoldTime));
- _mutex.downgrade();
+ Lock sync(*this);
+ _waitWrite = true;
+ notify();
}
+ //
+ // Acquire a read lock.
+ //
+ RWRecMutex::WLock sync(_m);
- ThreadControl::sleep(Time::seconds(_readHoldTime));
- _mutex.unlock();
+ {
+ Lock sync(*this);
+ _hasLock = true;
+ notify();
+
+ while(!_destroyed)
+ {
+ wait();
+ }
+ }
}
- bool
- upgradeSucceeded()
+ void
+ waitWrite()
{
- return _upgradeSucceeded;
- }
+ Lock sync(*this);
-private:
-
- int _waitTime;
- int _initialDelay;
- int _upgradeDelay;
- int _writeHoldTime;
- int _readHoldTime;
- bool _upgradeSucceeded;
-};
-typedef Handle<TimedUpgradeThread> TimedUpgradeThreadPtr;
+ //
+ // Wait for the _upgrading flag to be set.
+ //
+ while(!_waitWrite)
+ {
+ wait();
+ }
-class WriteThread : public RWRecMutexTestThread
-{
-public:
+ //
+ // Its necessary to sleep for 1 second to ensure that the
+ // thread is actually IN the upgrade and waiting.
+ //
+ ThreadControl::sleep(Time::seconds(1));
+ }
- WriteThread(RWRecMutex& m, int initialDelay, int writeHoldTime, int readHoldTime)
- : RWRecMutexTestThread(m),
- _initialDelay(initialDelay),
- _writeHoldTime(writeHoldTime),
- _readHoldTime(readHoldTime),
- _hasLock(false)
+ void
+ destroy()
{
+ Lock sync(*this);
+ _destroyed = true;
+ notify();
}
- virtual void
- run()
+ bool
+ hasLock()
{
- ThreadControl::sleep(Time::seconds(_initialDelay));
- _mutex.writeLock();
- _hasLock = true;
-
- ThreadControl::sleep(Time::seconds(_writeHoldTime));
- _mutex.downgrade();
- _hasLock = false;
-
- ThreadControl::sleep(Time::seconds(_readHoldTime));
- _mutex.unlock();
+ Lock sync(*this);
+ return _hasLock;
}
bool
- hasLock()
+ waitHasLock()
{
- return _hasLock;
+ Lock sync(*this);
+ if(!_hasLock)
+ {
+ timedWait(Time::seconds(1));
+ }
+ return _hasLock;
}
private:
- int _initialDelay;
- int _writeHoldTime;
- int _readHoldTime;
+ RWRecMutex& _m;
+ bool _destroyed;
+ bool _waitWrite;
bool _hasLock;
};
-typedef Handle<WriteThread> WriteThreadPtr;
+typedef Handle<RWRecMutexWriteThread> RWRecMutexWriteThreadPtr;
+
+RWRecMutexTest::RWRecMutexTest() :
+ TestBase(rwRecMutexTestName)
+{
+}
void
RWRecMutexTest::run()
@@ -704,77 +750,91 @@ RWRecMutexTest::run()
{
mutex.readLock();
- UpgradeThreadPtr t1 = new UpgradeThread(mutex, 0, 1, 0, 0);
- UpgradeThreadPtr t2 = new UpgradeThread(mutex, 0, 2, 0, 0);
-
+ RWRecMutexUpgradeThreadPtr t1 = new RWRecMutexUpgradeThread(mutex);
ThreadControl control1 = t1->start();
- ThreadControl control2 = t2->start();
+ //
+ // Wait for the thread to get into the upgrade call. The
+ // upgrade will hang since the readLock is held by this thread
+ // and therefore cannot succeed until we release our read
+ // lock.
+ //
+ t1->waitUpgrade();
+
+ try
+ {
+ mutex.upgrade();
+ test(false);
+ }
+ catch(const DeadlockException&)
+ {
+ }
+
+ //
+ // Release the waiting thread, join.
+ //
mutex.unlock();
- ThreadControl::sleep(Time::seconds(5));
-
- test(!t1->deadlock());
- test(t2->deadlock());
+ t1->destroy();
control1.join();
- control2.join();
+
+ test(!t1->failed());
}
// TEST: Same as previous test, but for a timedUpgrade.
{
mutex.readLock();
- UpgradeThreadPtr t1 = new UpgradeThread(mutex, 0, 0, 3, 0);
- TimedUpgradeThreadPtr t2 = new TimedUpgradeThread(mutex, 1, 0, 2, 0, 0);
-
+ RWRecMutexUpgradeThreadPtr t1 = new RWRecMutexUpgradeThread(mutex, true);
ThreadControl control1 = t1->start();
- ThreadControl control2 = t2->start();
-
- mutex.unlock();
- ThreadControl::sleep(Time::seconds(5));
- test(!t1->deadlock());
- test(!t2->upgradeSucceeded());
-
- control1.join();
- control2.join();
- }
+ t1->waitUpgrade();
- // TEST: Check that timedUpgrade() acquires the write lock.
- {
- mutex.readLock();
-
- TimedUpgradeThreadPtr t = new TimedUpgradeThread(mutex, 2, 0, 0, 0, 0);
-
- ThreadControl control = t->start();
- ThreadControl::sleep(Time::seconds(1));
+ try
+ {
+ mutex.upgrade();
+ test(false);
+ }
+ catch(const DeadlockException&)
+ {
+ }
+ //
+ // Release the waiting thread, join.
+ //
mutex.unlock();
- ThreadControl::sleep(Time::seconds(1));
+ t1->destroy();
+ control1.join();
- test(t->upgradeSucceeded());
-
- control.join();
+ test(!t1->failed());
}
// TEST: Check that an upgrader is given preference over a writer.
{
mutex.readLock();
- UpgradeThreadPtr t1 = new UpgradeThread(mutex, 0, 0, 2, 0);
- WriteThreadPtr t2 = new WriteThread(mutex, 0, 3, 0);
+ RWRecMutexUpgradeThreadPtr t1 = new RWRecMutexUpgradeThread(mutex);
+ RWRecMutexWriteThreadPtr t2 = new RWRecMutexWriteThread(mutex);
ThreadControl control1 = t1->start();
ThreadControl control2 = t2->start();
+ t1->waitUpgrade();
+ t2->waitWrite();
+
+ //
+ // This lets the upgrade continue. At this point t1 should
+ // have the write-lock, and t2 should not.
+ //
+ test(!t2->hasLock());
mutex.unlock();
- ThreadControl::sleep(Time::seconds(1));
- test(t1->hasUpgrade());
+ test(t1->waitHasLock());
test(!t2->hasLock());
+ t1->destroy();
+ t2->destroy();
+
+ test(t2->waitHasLock());
- ThreadControl::sleep(Time::seconds(2));
- test(t2->hasLock());
-
control1.join();
control2.join();
}