// ========================= private void PeekWakesUpTest(DiskQueue <int> queue) { Barrier bar = new Barrier(3); AtomicNullableBool peekResult = new AtomicNullableBool(); AtomicNullableBool peekResult2 = new AtomicNullableBool(); Task task = Task.Run(() => { bar.SignalAndWait(); int item = 0; peekResult.Value = queue.TryPeek(out item, 60000); Assert.AreEqual(100, item); }); Task task2 = Task.Run(() => { bar.SignalAndWait(); int item = 0; peekResult2.Value = queue.TryPeek(out item, 60000); Assert.AreEqual(100, item); }); bar.SignalAndWait(); Thread.Sleep(10); Assert.IsFalse(peekResult.HasValue); Assert.IsFalse(peekResult2.HasValue); queue.Add(100); TimingAssert.AreEqual(10000, true, () => peekResult.Value); TimingAssert.AreEqual(10000, true, () => peekResult2.Value); Task.WaitAll(task, task2); }
// ========================= private void TimeoutWorksTest(DiskQueue <int> queue) { Barrier bar = new Barrier(2); AtomicNullableBool takeResult = new AtomicNullableBool(); AtomicNullableBool peekResult = new AtomicNullableBool(); AtomicNullableBool addResult = new AtomicNullableBool(); Task task = Task.Run(() => { bar.SignalAndWait(); int item = 0; takeResult.Value = queue.TryTake(out item, 100); peekResult.Value = queue.TryPeek(out item, 100); while (queue.TryAdd(-1)) { ; } addResult.Value = queue.TryAdd(100, 100); }); bar.SignalAndWait(); TimingAssert.AreEqual(10000, false, () => takeResult.Value, "take"); TimingAssert.AreEqual(10000, false, () => peekResult.Value, "peek"); TimingAssert.AreEqual(10000, false, () => addResult.Value, "Add"); task.Wait(); }
// ============================== private void TestSimpleAddTakePeek(DiskQueue <int> queue) { Assert.AreEqual(0, queue.Count); Assert.IsTrue(queue.IsEmpty); Assert.IsTrue(queue.TryAdd(1)); Assert.AreEqual(1, queue.Count); Assert.IsFalse(queue.IsEmpty); int item = 0; Assert.IsTrue(queue.TryPeek(out item)); Assert.AreEqual(1, item); Assert.IsFalse(queue.IsEmpty); item = 0; Assert.IsTrue(queue.TryTake(out item)); Assert.AreEqual(1, item); Assert.AreEqual(0, queue.Count); Assert.IsTrue(queue.IsEmpty); for (int i = 1; i < 1000; i++) { if (i % 2 == 0) { queue.Add(i); } else { queue.AddForced(i); } Assert.AreEqual(i, queue.Count); } int itemNum = 0; while (queue.TryTake(out item)) { itemNum++; Assert.AreEqual(itemNum, item); } Assert.AreEqual(999, itemNum); Assert.AreEqual(0, queue.Count); Assert.IsTrue(queue.IsEmpty); }
// ========================= private void CancellationWorksTest(DiskQueue <int> queue) { Barrier bar = new Barrier(2); CancellationTokenSource takeSource = new CancellationTokenSource(); AtomicInt takeResult = new AtomicInt(); CancellationTokenSource peekSource = new CancellationTokenSource(); AtomicInt peekResult = new AtomicInt(); CancellationTokenSource addSource = new CancellationTokenSource(); AtomicInt addResult = new AtomicInt(); Task task = Task.Run(() => { bar.SignalAndWait(); int item = 0; try { takeResult.Value = queue.TryTake(out item, 60000, takeSource.Token) ? 1 : -1; } catch (OperationCanceledException) { takeResult.Value = 3; } try { peekResult.Value = queue.TryPeek(out item, 60000, peekSource.Token) ? 1 : -1; } catch (OperationCanceledException) { peekResult.Value = 3; } while (queue.TryAdd(-1)) { ; } try { addResult.Value = queue.TryAdd(100, 60000, addSource.Token) ? 1 : -1; } catch (OperationCanceledException) { addResult.Value = 3; } }); bar.SignalAndWait(); Thread.Sleep(10); Assert.AreEqual(0, takeResult); takeSource.Cancel(); TimingAssert.AreEqual(10000, 3, () => takeResult); Thread.Sleep(10); Assert.AreEqual(0, peekResult); peekSource.Cancel(); TimingAssert.AreEqual(10000, 3, () => peekResult); Thread.Sleep(10); Assert.AreEqual(0, addResult); addSource.Cancel(); TimingAssert.AreEqual(10000, 3, () => addResult); task.Wait(); }
// ================================== private void RunComplexTest(DiskQueue <int> q, int elemCount, int thCount) { int atomicRandom = 0; int trackElemCount = elemCount; int addFinished = 0; Thread[] threadsTake = new Thread[thCount]; Thread[] threadsAdd = new Thread[thCount]; CancellationTokenSource tokSrc = new CancellationTokenSource(); List <int> global = new List <int>(elemCount); Action addAction = () => { Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2); while (true) { int item = Interlocked.Decrement(ref trackElemCount); if (item < 0) { break; } if (rnd.Next(100) == 0) { q.AddForced(item); } else { q.Add(item); } int sleepTime = rnd.Next(12); int tmpItem = 0; if (q.TryPeek(out tmpItem) && tmpItem == item) { sleepTime += 15; } if (sleepTime > 0) { SpinWaitHelper.SpinWait(sleepTime); } } Interlocked.Increment(ref addFinished); }; Action takeAction = () => { Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2); List <int> data = new List <int>(); try { while (Volatile.Read(ref addFinished) < thCount) { int tmp = 0; if (q.TryTake(out tmp, -1, tokSrc.Token)) { data.Add((int)tmp); } int sleepTime = rnd.Next(12); if (sleepTime > 0) { SpinWaitHelper.SpinWait(sleepTime); } } } catch (OperationCanceledException) { } int tmp2; while (q.TryTake(out tmp2)) { data.Add((int)tmp2); } lock (global) global.AddRange(data); }; for (int i = 0; i < threadsTake.Length; i++) { threadsTake[i] = new Thread(new ThreadStart(takeAction)); } for (int i = 0; i < threadsAdd.Length; i++) { threadsAdd[i] = new Thread(new ThreadStart(addAction)); } for (int i = 0; i < threadsTake.Length; i++) { threadsTake[i].Start(); } for (int i = 0; i < threadsAdd.Length; i++) { threadsAdd[i].Start(); } for (int i = 0; i < threadsAdd.Length; i++) { threadsAdd[i].Join(); } tokSrc.Cancel(); for (int i = 0; i < threadsTake.Length; i++) { threadsTake[i].Join(); } Assert.AreEqual(elemCount, global.Count); global.Sort(); for (int i = 0; i < elemCount; i++) { Assert.AreEqual(i, global[i]); } }