WaitForCondition() public static method

public static WaitForCondition ( Func condition ) : void
condition Func
return void
        public static void AtomicDowngradeTest()
        {
            var trwl = new TestReaderWriterLock();

            trwl.AcquireReaderLock();
            TestLockCookie tlc = trwl.UpgradeToWriterLock();

            Action waitForWaitingWriter;
            Thread waitingWriter =
                ThreadTestHelpers.CreateGuardedThread(out waitForWaitingWriter, () =>
            {
                trwl.AcquireWriterLock();
                trwl.ReleaseWriterLock();
            });

            waitingWriter.Start();
            ThreadTestHelpers.WaitForCondition(() => (waitingWriter.ThreadState & ThreadState.WaitSleepJoin) != 0);

            // Downgrade to a read lock successfully while there is a waiting writer
            trwl.DowngradeFromWriterLock(tlc);

            // Releasing the read lock releases the waiting writer
            trwl.ReleaseReaderLock();
            waitForWaitingWriter();

            trwl.Dispose();
        }
        public static void AtomicRecursiveReaderTest()
        {
            var trwl = new TestReaderWriterLock();

            trwl.AcquireReaderLock();

            Action waitForWaitingWriter;
            Thread waitingWriter =
                ThreadTestHelpers.CreateGuardedThread(out waitForWaitingWriter, () =>
            {
                trwl.AcquireWriterLock();
                trwl.ReleaseWriterLock();
            });

            waitingWriter.Start();
            ThreadTestHelpers.WaitForCondition(() => (waitingWriter.ThreadState & ThreadState.WaitSleepJoin) != 0);

            // Acquire a recursive read lock successfully while there is a waiting writer
            trwl.AcquireReaderLock();

            // Releasing both read locks releases the waiting writer
            trwl.ReleaseLock();
            waitForWaitingWriter();

            trwl.Dispose();
        }
        public static void WaitingWritersTest()
        {
            var trwl = new TestReaderWriterLock();

            trwl.AcquireReaderLock();

            Action acquireReleaseWriterLock =
                () =>
            {
                trwl.AcquireWriterLock();
                trwl.ReleaseWriterLock();
            };
            Action waitForWaitingWriter1, waitForWaitingWriter2;
            Thread waitingWriter1 = ThreadTestHelpers.CreateGuardedThread(out waitForWaitingWriter1, acquireReleaseWriterLock);
            Thread waitingWriter2 = ThreadTestHelpers.CreateGuardedThread(out waitForWaitingWriter2, acquireReleaseWriterLock);

            waitingWriter1.IsBackground = true;
            waitingWriter2.IsBackground = true;
            waitingWriter1.Start();
            waitingWriter2.Start();
            ThreadTestHelpers.WaitForCondition(() => (waitingWriter1.ThreadState & ThreadState.WaitSleepJoin) != 0);
            ThreadTestHelpers.WaitForCondition(() => (waitingWriter2.ThreadState & ThreadState.WaitSleepJoin) != 0);

            // Releasing the read lock releases a waiting writer, that writer releases its write lock, in turn releasing the
            // other writer
            trwl.ReleaseReaderLock();
            waitForWaitingWriter1();
            waitForWaitingWriter2();

            trwl.Dispose();
        }
        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();
        }
Example #5
0
        public static void TimersCreatedConcurrentlyOnDifferentThreadsAllFire()
        {
            int processorCount = Environment.ProcessorCount;

            int           timerTickCount = 0;
            TimerCallback timerCallback  = data => Interlocked.Increment(ref timerTickCount);

            var             threadStarted          = new AutoResetEvent(false);
            var             createTimers           = new ManualResetEvent(false);
            var             timers                 = new Timer[processorCount];
            Action <object> createTimerThreadStart = data =>
            {
                int i  = (int)data;
                var sw = new Stopwatch();
                threadStarted.Set();
                createTimers.WaitOne();

                // Use the CPU a bit around creating the timer to try to have some of these threads run concurrently
                sw.Restart();
                do
                {
                    Thread.SpinWait(1000);
                } while (sw.ElapsedMilliseconds < 10);

                timers[i] = new Timer(timerCallback, null, 1, Timeout.Infinite);

                // Use the CPU a bit around creating the timer to try to have some of these threads run concurrently
                sw.Restart();
                do
                {
                    Thread.SpinWait(1000);
                } while (sw.ElapsedMilliseconds < 10);
            };

            var waitsForThread = new Action[timers.Length];

            for (int i = 0; i < timers.Length; ++i)
            {
                var t = ThreadTestHelpers.CreateGuardedThread(out waitsForThread[i], createTimerThreadStart);
                t.IsBackground = true;
                t.Start(i);
                threadStarted.CheckedWait();
            }

            createTimers.Set();
            ThreadTestHelpers.WaitForCondition(() => timerTickCount == timers.Length);

            foreach (var waitForThread in waitsForThread)
            {
                waitForThread();
            }
        }
        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();
        }
Example #7
0
        public void AbandonExisting(
            string name,
            WaitHandleWaitType waitType,
            int waitCount,
            int notAbandonedWaitIndex,
            bool isNotAbandonedWaitObjectSignaled,
            bool abandonDuringWait)
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                using (var m = new Mutex(false, name))
                    using (Mutex m2 = waitCount == 1 ? null : new Mutex(false, name == null ? null : name + "_2"))
                        using (ManualResetEvent e = waitCount == 1 ? null : new ManualResetEvent(isNotAbandonedWaitObjectSignaled))
                            using (ManualResetEvent threadReadyForAbandon = abandonDuringWait ? new ManualResetEvent(false) : null)
                                using (ManualResetEvent abandonSoon = abandonDuringWait ? new ManualResetEvent(false) : null)
                                {
                                    WaitHandle[] waitHandles = null;
                                    if (waitType != WaitHandleWaitType.WaitOne)
                                    {
                                        waitHandles = new WaitHandle[waitCount];
                                        if (waitCount == 1)
                                        {
                                            waitHandles[0] = m;
                                        }
                                        else
                                        {
                                            waitHandles[notAbandonedWaitIndex] = e;
                                            waitHandles[notAbandonedWaitIndex == 0 ? 1 : 0] = m;
                                            waitHandles[notAbandonedWaitIndex == 2 ? 1 : 2] = m2;
                                        }
                                    }

                                    Thread t = ThreadTestHelpers.CreateGuardedThread(out Action waitForThread, () =>
                                    {
                                        Assert.True(m.WaitOne(0));
                                        if (m2 != null)
                                        {
                                            Assert.True(m2.WaitOne(0));
                                        }

                                        if (abandonDuringWait)
                                        {
                                            threadReadyForAbandon.Set();
                                            abandonSoon.CheckedWait();
                                            Thread.Sleep(ThreadTestHelpers.ExpectedTimeoutMilliseconds);
                                        }

                                        // don't release the mutexes; abandon them on this thread
                                    });
                                    t.IsBackground = true;
                                    t.Start();

                                    if (abandonDuringWait)
                                    {
                                        threadReadyForAbandon.CheckedWait();
                                        abandonSoon.Set();
                                    }
                                    else
                                    {
                                        waitForThread();
                                    }

                                    AbandonedMutexException ame;
                                    switch (waitType)
                                    {
                                    case WaitHandleWaitType.WaitOne:
                                        ame =
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        Assert.Equal(-1, ame.MutexIndex);
                                        Assert.Null(ame.Mutex);
                                        break;

                                    case WaitHandleWaitType.WaitAny:
                                        if (waitCount != 1 && isNotAbandonedWaitObjectSignaled && notAbandonedWaitIndex == 0)
                                        {
                                            Assert.Equal(0, WaitHandle.WaitAny(waitHandles, 0));
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m2.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                            break;
                                        }

                                        if (waitCount != 1 && isNotAbandonedWaitObjectSignaled && notAbandonedWaitIndex != 0)
                                        {
                                            ame =
                                                Assert.Throws <AbandonedMutexException>(() =>
                                            {
                                                ThreadTestHelpers.WaitForCondition(() =>
                                                {
                                                    // Actually expecting an exception from WaitAny(), but there may be a delay before
                                                    // the mutex is actually released and abandoned. If there is no exception, the
                                                    // WaitAny() must have succeeded due to the event being signaled.
                                                    int r = WaitHandle.WaitAny(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds);
                                                    Assert.Equal(notAbandonedWaitIndex, r);
                                                    return(false);
                                                });
                                            });
                                        }
                                        else
                                        {
                                            ame =
                                                AssertExtensions.Throws <AbandonedMutexException, int>(
                                                    () => WaitHandle.WaitAny(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        }

                                        // Due to a potential delay in abandoning mutexes, either mutex may have been seen to be
                                        // abandoned first
                                        Assert.True(ame.Mutex == m || (m2 != null && ame.Mutex == m2));
                                        int mIndex  = waitCount != 1 && notAbandonedWaitIndex == 0 ? 1 : 0;
                                        int m2Index = waitCount != 1 && notAbandonedWaitIndex == 2 ? 1 : 2;
                                        if (ame.Mutex == m)
                                        {
                                            Assert.Equal(mIndex, ame.MutexIndex);
                                        }
                                        else
                                        {
                                            Assert.True(m2Index < notAbandonedWaitIndex);
                                            Assert.Equal(m2Index, ame.MutexIndex);
                                        }

                                        // Verify that the other mutex also gets abandoned
                                        if (ame.MutexIndex == mIndex)
                                        {
                                            if (m2 != null)
                                            {
                                                AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                    () => m2.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                            }
                                        }
                                        else
                                        {
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        }

                                        break;

                                    case WaitHandleWaitType.WaitAll:
                                        if (waitCount != 1 && !isNotAbandonedWaitObjectSignaled)
                                        {
                                            Assert.False(WaitHandle.WaitAll(waitHandles, ThreadTestHelpers.ExpectedTimeoutMilliseconds * 2));
                                            Assert.True(e.Set());
                                        }

                                        ame =
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => WaitHandle.WaitAll(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        Assert.Equal(-1, ame.MutexIndex);
                                        Assert.Null(ame.Mutex);
                                        break;
                                    }

                                    if (abandonDuringWait)
                                    {
                                        waitForThread();
                                    }

                                    m.ReleaseMutex();
                                    m2?.ReleaseMutex();
                                }
            });
        }