📄 rwrecmutextest.cpp
字号:
} bool hasWriteLock() { Lock sync(*this); return _hasWriteLock; } // // This waits a maximum of N seconds if the lock is not already // acquired. It could while forever, but that would cause the test // to hang in the event of a failure. // bool waitHasWriteLock() { Lock sync(*this); if(!_hasWriteLock) { timedWait(Time::seconds(10)); } return _hasWriteLock; }private: RWRecMutex& _m; bool _destroyed; bool _waitWrite; bool _hasWriteLock;};typedef Handle<RWRecMutexWriteThread> RWRecMutexWriteThreadPtr;RWRecMutexTest::RWRecMutexTest() : TestBase(rwRecMutexTestName){}voidRWRecMutexTest::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 // TEST: Ensure that only one reader can upgrade to a writer. // Other readers get a DeadlockException. { mutex.readLock(); RWRecMutexUpgradeThreadPtr t1 = new RWRecMutexUpgradeThread(mutex); ThreadControl control1 = t1->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(); // // Its necessary to sleep for 1 second to ensure that the // thread is actually IN the upgrade and waiting. // ThreadControl::sleep(Time::seconds(1)); try { mutex.upgrade(); test(false); } catch(const DeadlockException&) { } // // Release the waiting thread, join. // mutex.unlock(); t1->destroy(); control1.join(); test(!t1->failed()); } // TEST: Same as previous test, but for a timedUpgrade. { mutex.readLock(); RWRecMutexUpgradeThreadPtr t1 = new RWRecMutexUpgradeThread(mutex, true); ThreadControl control1 = t1->start(); t1->waitUpgrade(); // // Its necessary to sleep for 1 second to ensure that the // thread is actually IN the upgrade and waiting. // ThreadControl::sleep(Time::seconds(1)); try { mutex.upgrade(); test(false); } catch(const DeadlockException&) { } // // Release the waiting thread, join. // mutex.unlock(); t1->destroy(); control1.join(); test(!t1->failed()); } // TEST: Check that an upgrader is given preference over a writer. { mutex.readLock(); RWRecMutexUpgradeThreadPtr t1 = new RWRecMutexUpgradeThread(mutex); ThreadControl control1 = t1->start(); // // Its not necessary to sleep here, since the upgrade thread // acquires the read lock before signalling. Therefore the // write thread cannot get the write lock. // t1->waitUpgrade();
RWRecMutexWriteThreadPtr t2 = new RWRecMutexWriteThread(mutex);
ThreadControl control2 = t2->start();
t2->waitWrite(); //
// Its necessary to sleep for 1 second to ensure that the
// thread is actually IN the write lock and waiting.
//
ThreadControl::sleep(Time::seconds(1));
// // Unlocking the read mutex lets the upgrade continue. At this // point t1 should have the write-lock, and t2 should not. // test(!t2->hasWriteLock()); mutex.unlock(); // // Wait for t1 to get the write lock. It will not release it // until the thread is destroyed. t2 should not have the write // lock. // test(!t1->failed()); test(t1->waitHasWriteLock()); test(!t2->hasWriteLock()); t1->destroy(); t2->destroy(); // // After the thread has terminated the thread must have // acquired the write lock. // test(t2->waitHasWriteLock()); control1.join(); control2.join(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -