public void TestCheckingEnterExitOwnership()
        {
            var monitor = new MonitorSimple();

            var finished = 0;

            var th = new Thread(() =>
            {
                monitor.Enter();
                while (finished == 0) { }
            }) { IsBackground = true };

            th.Start();

            WaitAlittle();

            AssertEx.Throws<SynchronizationLockException>(() => monitor.Exit());

            Thread.VolatileWrite(ref finished, 1);
        }
Exemple #2
0
 public LockHandle(MonitorSimple source)
 {
     _source = source;
 }
        public void TestEnterExitInGeneral()
        {
            const int threadCount = 10;
            const int iterations = 100000;

            long n = 0;

            var montor = new MonitorSimple();

            RunSimultanously(threadCount, () =>
            {
                for (var i = 0; i < iterations; i++)
                {
                    using (montor.GetLocked())
                    using (montor.GetLocked())
                    using (montor.GetLocked())
                    {
                        n = n + 1;
                        if (i % 100 == 0)
                            Thread.SpinWait(10000);
                    }
                }
            }, true);

            var expected = Enumerable.Repeat(1, iterations).Sum() * threadCount;
            Assert.AreEqual(expected, n);
        }
        public void TestWait()
        {
            var e = new ManualResetEvent(false);
            var m = new MonitorSimple();

            var testValue = 0;

            var th1 = new Thread(() =>
            {
                m.Enter();
                testValue = 1;
                e.WaitOne();

                m.Wait();
                testValue = 2;
                m.Exit();
            }) { Name = "th1" };

            var th2 = new Thread(() =>
            {
                m.Enter();
                testValue = 100;
                m.Exit();
            }) { Name = "th2" };

            th1.Start();

            WaitAlittle();

            th2.Start();

            WaitAlittle();

            Assert.AreEqual(1, testValue);

            e.Set();

            WaitAlittle();

            Assert.AreEqual(100, testValue);

            m.Enter();
            m.PulseAll();
            m.Exit();

            WaitAlittle();

            Assert.AreEqual(2, testValue);
        }
        public void TestStressWait()
        {
            const int iterations = 1000000;
            const int doHardWorkBeforeEachNthProducing = iterations / 100;
            var threadCount = Environment.ProcessorCount;

            var src = 0;
            var dst = 0;
            var addingCompleted = false;

            var m = new MonitorSimple();

            var readers = RunSimultanously(threadCount, () =>
            {
                while (true)
                {
                    using (m.GetLocked())
                    using (m.GetLocked())
                    using (m.GetLocked())
                    {
                        while (src == 0 && !addingCompleted)
                            m.Wait();

                        if (addingCompleted && src == 0)
                            break;

                        src = src - 1;
                        dst = dst + 1;
                    }
                }
            }, false);

            RunSimultanously(threadCount, () =>
            {
                for (var i = 0; i < iterations; i++)
                {
                    if (i % doHardWorkBeforeEachNthProducing == 0)
                        DoHardWork();

                    using (m.GetLocked())
                    using (m.GetLocked()) //for extra stressing
                    {
                        src = src + 1;

                        // such a weird construct is for extra stressing
                        if (i % 2 == 0)
                            m.Pulse();
                        else
                            m.PulseAll();
                    }
                }
            }, true);

            using (m.GetLocked())
            {
                addingCompleted = true;
                m.PulseAll();
            }

            readers.ForEach(r => r.Join());

            var expected = Enumerable.Repeat(1, iterations).Sum() * threadCount;

            Assert.AreEqual(expected, dst);
        }
        public void TestStressLockedSectionsDoNotOverlapp()
        {
            const int iterations = 100000;

            var entered = 0;
            var overlapped = false;

            var m = new MonitorSimple();

            RunSimultanously(5, () =>
            {
                for (var i = 0; i < iterations; i++)
                {
                    using (m.GetLocked())
                    using (m.GetLocked())
                    {
                        if (Interlocked.CompareExchange(ref entered, 1, 0) != 0)
                            overlapped = true;

                        Thread.SpinWait(i % 100 == 0 ? 10000 : 1);

                        if (Interlocked.CompareExchange(ref entered, 0, 1) != 1)
                            overlapped = true;
                    }
                }
            }, true);

            Assert.IsTrue(entered == 0);
            Assert.IsFalse(overlapped);
        }