public void TestCheckingWaitPulseOwnership() { var monitor = new MonitorSimple(); var finished = 0; AssertEx.Throws<SynchronizationLockException>(() => { monitor.Wait(); }); AssertEx.Throws<SynchronizationLockException>(() => { monitor.Pulse(); }); AssertEx.Throws<SynchronizationLockException>(() => { monitor.PulseAll(); }); var th = new Thread(() => { monitor.Enter(); while (finished == 0) { } }) { IsBackground = true }; th.Start(); WaitAlittle(); // other thread has lock AssertEx.Throws<SynchronizationLockException>(() => { monitor.Wait(); }); AssertEx.Throws<SynchronizationLockException>(() => { monitor.Pulse(); }); AssertEx.Throws<SynchronizationLockException>(() => { monitor.PulseAll(); }); Thread.VolatileWrite(ref finished, 1); }
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); }