// ********************************************************************** // // Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #include #include #include using namespace std; using namespace IceUtil; class MonitorRecMutexTestThread : public Thread { public: MonitorRecMutexTestThread(Monitor& m) : _monitor(m), _tryLock(false) { } virtual void run() { Monitor::TryLock tlock(_monitor); test(!tlock.acquired()); { Mutex::Lock lock(_tryLockMutex); _tryLock = true; } _tryLockCond.signal(); Monitor::Lock lock(_monitor); } void waitTryLock() { Mutex::Lock lock(_tryLockMutex); while(!_tryLock) { _tryLockCond.wait(lock); } } private: Monitor& _monitor; bool _tryLock; // // Use native Condition variable here, not Monitor. // Cond _tryLockCond; Mutex _tryLockMutex; }; typedef Handle MonitorRecMutexTestThreadPtr; class MonitorRecMutexTestThread2 : public Thread, public Monitor { public: MonitorRecMutexTestThread2(Monitor& monitor) : finished(false), _monitor(monitor) { } virtual void run() { Monitor::Lock lock(_monitor); _monitor.wait(); finished = true; } bool finished; private: Monitor& _monitor; }; typedef Handle MonitorRecMutexTestThread2Ptr; static const string monitorRecMutexTestName("monitor"); MonitorRecMutexTest::MonitorRecMutexTest() : TestBase(monitorRecMutexTestName) { } void MonitorRecMutexTest::run() { Monitor monitor; MonitorRecMutexTestThreadPtr t; MonitorRecMutexTestThread2Ptr t2; MonitorRecMutexTestThread2Ptr t3; ThreadControl control; ThreadControl control2; { Monitor::Lock lock(monitor); Monitor::TryLock lock2(monitor); test(lock2.acquired()); // TEST: TryLock Monitor::TryLock tlock(monitor); test(tlock.acquired()); // TEST: Start thread, try to acquire the mutex. t = new MonitorRecMutexTestThread(monitor); 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: notify() wakes one consumer. t2 = new MonitorRecMutexTestThread2(monitor); control = t2->start(); t3 = new MonitorRecMutexTestThread2(monitor); control2 = t3->start(); // Give the thread time to start waiting. ThreadControl::sleep(Time::seconds(1)); { Monitor::Lock lock(monitor); monitor.notify(); } // Give one thread time to terminate ThreadControl::sleep(Time::seconds(1)); test((t2->finished && !t3->finished) || (t3->finished && !t2->finished)); { Monitor::Lock lock(monitor); monitor.notify(); } control.join(); control2.join(); // TEST: notifyAll() wakes one consumer. t2 = new MonitorRecMutexTestThread2(monitor); control = t2->start(); t3 = new MonitorRecMutexTestThread2(monitor); control2 = t3->start(); // Give the threads time to start waiting. ThreadControl::sleep(Time::seconds(1)); { Monitor::Lock lock(monitor); monitor.notifyAll(); } control.join(); control2.join(); // TEST: timedWait { Monitor::Lock lock(monitor); test(!monitor.timedWait(Time::milliSeconds(500))); } }