public static void ReadersWaitingOnWaitingUpgraderTest()
{
var trwl = new TestReaderWriterLock();
trwl.AcquireReaderLock();
var waitingUpgraderReady = new AutoResetEvent(false);
var continueWaitingUpgrader = new AutoResetEvent(false);
Action waitForWaitingUpgrader;
Thread waitingUpgrader =
ThreadTestHelpers.CreateGuardedThread(out waitForWaitingUpgrader, () =>
{
trwl.AcquireReaderLock();
trwl.UpgradeToWriterLock();
waitingUpgraderReady.Set();
continueWaitingUpgrader.CheckedWait();
trwl.ReleaseWriterLock();
trwl.VerifyIsReaderLockHeld(false);
trwl.VerifyIsWriterLockHeld(false);
});
waitingUpgrader.IsBackground = true;
waitingUpgrader.Start();
ThreadTestHelpers.WaitForCondition(() => (waitingUpgrader.ThreadState & ThreadState.WaitSleepJoin) != 0);
Action acquireReleaseReaderLock =
() =>
{
trwl.AcquireReaderLock();
trwl.ReleaseReaderLock();
};
Action waitForWaitingReader1, waitForWaitingReader2;
Thread waitingReader1 = ThreadTestHelpers.CreateGuardedThread(out waitForWaitingReader1, acquireReleaseReaderLock);
Thread waitingReader2 = ThreadTestHelpers.CreateGuardedThread(out waitForWaitingReader2, acquireReleaseReaderLock);
waitingReader1.IsBackground = true;
waitingReader2.IsBackground = true;
waitingReader1.Start();
waitingReader2.Start();
ThreadTestHelpers.WaitForCondition(() => (waitingReader1.ThreadState & ThreadState.WaitSleepJoin) != 0);
ThreadTestHelpers.WaitForCondition(() => (waitingReader2.ThreadState & ThreadState.WaitSleepJoin) != 0);
// Releasing the read lock releases the waiting upgrader
trwl.ReleaseReaderLock();
waitingUpgraderReady.CheckedWait();
// Releasing the now-writer's write lock releases all waiting readers
continueWaitingUpgrader.Set();
waitForWaitingUpgrader();
waitForWaitingReader1();
waitForWaitingReader2();
trwl.Dispose();
}