// ********************************************************************** // // Copyright (c) 2003 // ZeroC, Inc. // Billerica, MA, USA // // All Rights Reserved. // // Ice is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License version 2 as published by // the Free Software Foundation. // // ********************************************************************** #include #include #include using namespace std; using namespace IceUtil; class MonitorMutexTestThread : public Thread { public: MonitorMutexTestThread(Monitor& m) : _monitor(m), _trylock(false) { } virtual void run() { try { Monitor::TryLock lock(_monitor); test(false); } catch(const ThreadLockedException&) { // Expected } _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 MonitorMutexTestThreadPtr; class MonitorMutexTestThread2 : public Thread { public: MonitorMutexTestThread2(Monitor& monitor) : finished(false), _monitor(monitor) { } virtual void run() { Monitor::Lock lock(_monitor); _monitor.wait(); finished = true; } bool finished; private: Monitor& _monitor; }; typedef Handle MonitorMutexTestThread2Ptr; static const string monitorMutexTestName("monitor"); MonitorMutexTest::MonitorMutexTest() : TestBase(monitorMutexTestName) { } void MonitorMutexTest::run() { Monitor monitor; MonitorMutexTestThreadPtr t; MonitorMutexTestThread2Ptr t2; MonitorMutexTestThread2Ptr t3; ThreadControl control; ThreadControl control2; { Monitor::Lock lock(monitor); // TEST: TryLock try { Monitor::TryLock lock(monitor); test(false); } catch(const ThreadLockedException&) { // Expected } // TEST: Start thread, try to acquire the mutex. t = new MonitorMutexTestThread(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 MonitorMutexTestThread2(monitor); control = t2->start(); t3 = new MonitorMutexTestThread2(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 MonitorMutexTestThread2(monitor); control = t2->start(); t3 = new MonitorMutexTestThread2(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))); } }