public static void WaitingUpgradersTest()
{
var trwl = new TestReaderWriterLock();
trwl.AcquireReaderLock();
var waitingUpgrader1AcquiredReadLock = new ManualResetEvent(false);
Action waitForWaitingUpgrader1, waitForWaitingUpgrader2, waitForWaitingUpgrader3;
Thread waitingUpgrader1 =
ThreadTestHelpers.CreateGuardedThread(out waitForWaitingUpgrader1, () =>
{
trwl.AcquireReaderLock();
waitingUpgrader1AcquiredReadLock.Set();
TestLockCookie tlc = trwl.UpgradeToWriterLock();
trwl.DowngradeFromWriterLock(tlc);
trwl.ReleaseReaderLock();
});
Action upgradeDowngradeLock =
() =>
{
TestLockCookie tlc = trwl.UpgradeToWriterLock();
trwl.DowngradeFromWriterLock(tlc);
};
Thread waitingUpgrader2 = ThreadTestHelpers.CreateGuardedThread(out waitForWaitingUpgrader2, upgradeDowngradeLock);
Thread waitingUpgrader3 = ThreadTestHelpers.CreateGuardedThread(out waitForWaitingUpgrader3, upgradeDowngradeLock);
waitingUpgrader1.IsBackground = true;
waitingUpgrader2.IsBackground = true;
waitingUpgrader1.Start();
waitingUpgrader1AcquiredReadLock.CheckedWait();
waitingUpgrader2.Start();
waitingUpgrader3.Start();
ThreadTestHelpers.WaitForCondition(() => (waitingUpgrader1.ThreadState & ThreadState.WaitSleepJoin) != 0);
ThreadTestHelpers.WaitForCondition(() => (waitingUpgrader2.ThreadState & ThreadState.WaitSleepJoin) != 0);
ThreadTestHelpers.WaitForCondition(() => (waitingUpgrader3.ThreadState & ThreadState.WaitSleepJoin) != 0);
// Releasing the read lock releases a waiting upgrader, that writer downgrades its write lock, in turn releasing the
// other upgrader, and so on
trwl.ReleaseReaderLock();
waitForWaitingUpgrader1();
waitForWaitingUpgrader2();
waitForWaitingUpgrader3();
trwl.Dispose();
}