public void TestBlockRequiredCount() { PartialThreadBlocker inst = new PartialThreadBlocker(4); Barrier startBar = new Barrier(8 + 1); int exitedCount = 0; for (int i = 0; i < 8; i++) { Task.Run(() => { startBar.SignalAndWait(); inst.Wait(); Interlocked.Increment(ref exitedCount); }); } startBar.SignalAndWait(); Assert.IsTrue(SpinWait.SpinUntil(() => Volatile.Read(ref exitedCount) >= 4 && inst.RealWaiterCount >= 4, 4000)); TimingAssert.AreEqual(5000, 8 - 4, () => Volatile.Read(ref exitedCount), "exitedCount != 8"); TimingAssert.AreEqual(5000, 4, () => inst.ExpectedWaiterCount, "ExpectedWaiterCount != 4"); TimingAssert.AreEqual(5000, 4, () => inst.RealWaiterCount, "RealWaiterCount != 4"); inst.SetExpectedWaiterCount(0); TimingAssert.AreEqual(5000, 8, () => Volatile.Read(ref exitedCount), "exitedCount != 8"); TimingAssert.AreEqual(5000, 0, () => inst.ExpectedWaiterCount, "ExpectedWaiterCount != 0"); TimingAssert.AreEqual(5000, 0, () => inst.RealWaiterCount, "RealWaiterCount != 0"); }
public void TestIncreaseWaiters() { PartialThreadBlocker inst = new PartialThreadBlocker(4); Barrier startBar = new Barrier(8 + 1); int exitedCount = 0; int somethingWork = 0; CancellationTokenSource tokenSrc = new CancellationTokenSource(); for (int i = 0; i < 8; i++) { Task.Run(() => { startBar.SignalAndWait(); while (!tokenSrc.IsCancellationRequested) { inst.Wait(); Interlocked.Increment(ref somethingWork); Thread.Sleep(10); } Interlocked.Increment(ref exitedCount); }); } startBar.SignalAndWait(); TimingAssert.AreEqual(5000, 4, () => inst.ExpectedWaiterCount); TimingAssert.AreEqual(5000, 4, () => inst.RealWaiterCount, "Real waiter count != 4 (can be caused by slow processing)"); TimingAssert.IsTrue(5000, () => Volatile.Read(ref somethingWork) > 0); inst.SetExpectedWaiterCount(8); Assert.AreEqual(8, inst.ExpectedWaiterCount); TimingAssert.AreEqual(5000, 8, () => inst.RealWaiterCount); Interlocked.Exchange(ref somethingWork, 0); TimingAssert.IsTrue(5000, () => Volatile.Read(ref somethingWork) == 0); tokenSrc.Cancel(); inst.SetExpectedWaiterCount(0); TimingAssert.AreEqual(5000, 8, () => Volatile.Read(ref exitedCount)); TimingAssert.AreEqual(5000, 0, () => inst.ExpectedWaiterCount); TimingAssert.AreEqual(500, 0, () => inst.RealWaiterCount); }
public void TestCycledBlockRequiredCount() { PartialThreadBlocker inst = new PartialThreadBlocker(4); Barrier startBar = new Barrier(8 + 1); int exitedCount = 0; int somethingWork = 0; CancellationTokenSource tokenSrc = new CancellationTokenSource(); for (int i = 0; i < 8; i++) { Task.Run(() => { startBar.SignalAndWait(); while (!tokenSrc.IsCancellationRequested) { inst.Wait(); Interlocked.Increment(ref somethingWork); Thread.Sleep(10); } Interlocked.Increment(ref exitedCount); }); } startBar.SignalAndWait(); TimingAssert.AreEqual(5000, 4, () => inst.ExpectedWaiterCount); TimingAssert.AreEqual(5000, 4, () => inst.RealWaiterCount); TimingAssert.IsTrue(5000, () => Volatile.Read(ref somethingWork) > 0); tokenSrc.Cancel(); inst.SetExpectedWaiterCount(0); TimingAssert.AreEqual(5000, 8, () => Volatile.Read(ref exitedCount)); TimingAssert.AreEqual(5000, 0, () => inst.ExpectedWaiterCount); TimingAssert.AreEqual(5000, 0, () => inst.RealWaiterCount); }