public void ComplexInceptionTestNonOrdNoBcg() { using (var q = new LevelingQueue <int>(new MemoryQueue <int>(1000), new LevelingQueue <int>(new MemoryQueue <int>(1000), new MemoryQueue <int>(1000), LevelingQueueAddingMode.PreferLiveData, false), LevelingQueueAddingMode.PreferLiveData, false)) { RunComplexTest(q, 2000000, Math.Max(1, Environment.ProcessorCount / 2)); } using (var q = new LevelingQueue <int>(new MemoryQueue <int>(1000), new LevelingQueue <int>(new MemoryQueue <int>(1000), new MemoryQueue <int>(1000), LevelingQueueAddingMode.PreferLiveData, false), LevelingQueueAddingMode.PreferLiveData, false)) { RunComplexTest(q, 2000000, Math.Max(1, Environment.ProcessorCount / 2) + 2); } }
public void ComplexInceptionTestOrdBcg() { using (var q = new LevelingQueue <int>(new MemoryQueue <int>(1000), new LevelingQueue <int>(new MemoryQueue <int>(1000), new MemoryQueue <int>(1000), LevelingQueueAddingMode.PreserveOrder, true), LevelingQueueAddingMode.PreserveOrder, true)) { RunComplexTest(q, 2000000, Math.Max(1, Environment.ProcessorCount / 2)); } using (var q = new LevelingQueue <int>(new MemoryQueue <int>(1000), new LevelingQueue <int>(new MemoryQueue <int>(1000), new MemoryQueue <int>(1000), LevelingQueueAddingMode.PreserveOrder, true), LevelingQueueAddingMode.PreserveOrder, true)) { RunComplexTest(q, 2000000, Math.Max(1, Environment.ProcessorCount / 2) + 2); } }
// ========================= private void AddWakesUpTest(LevelingQueue <int> queue) { while (queue.TryAdd(100)) { ; // Fill queue } if (queue.IsBackgroundTransferingEnabled) { SpinWait sw = new SpinWait(); while (queue.IsBackgroundInWork && sw.Count < 100) { sw.SpinOnce(); } for (int i = 0; i < 100; i++) { queue.TryAdd(100); SpinWaitHelper.SpinWait(12); } } Barrier bar = new Barrier(2); int addResult = 0; Task task = Task.Run(() => { bar.SignalAndWait(); AtomicSet(ref addResult, queue.TryAdd(-100, 60000)); }); bar.SignalAndWait(); Thread.Sleep(10); Assert.AreEqual(0, Volatile.Read(ref addResult)); queue.Take(); if (queue.AddingMode == LevelingQueueAddingMode.PreserveOrder && !queue.IsBackgroundTransferingEnabled) { int item; while (queue.TryTake(out item)) { ; } } TimingAssert.AreEqual(10000, 1, () => Volatile.Read(ref addResult)); task.Wait(); }
private static TimeSpan RunConcurrentLvlQ(string name, int elemCount, int addThCount, int takeThCount, int addSpin, int takeSpin) { LevelingQueue <int> col = new LevelingQueue <int>( new MemoryQueue <int>(3000), //new MemoryQueue<int>(7000), new LevelingQueue <int>(new MemoryQueue <int>(3000), new MemoryQueue <int>(4000), LevelingQueueAddingMode.PreferLiveData, true), LevelingQueueAddingMode.PreserveOrder, false); CancellationTokenSource srcCancel = new CancellationTokenSource(); Thread[] addThreads = new Thread[addThCount]; Thread[] takeThreads = new Thread[takeThCount]; int addedElemCount = 0; List <int> globalList = new List <int>(); Barrier barierStart = new Barrier(1 + addThreads.Length + takeThreads.Length); Barrier barierAdders = new Barrier(1 + addThreads.Length); Barrier barierTakers = new Barrier(1 + takeThreads.Length); Action addAction = () => { barierStart.SignalAndWait(); int index = 0; while ((index = Interlocked.Increment(ref addedElemCount)) <= elemCount) { col.Add(index - 1); Thread.SpinWait(addSpin); } barierAdders.SignalAndWait(); }; Action takeAction = () => { CancellationToken myToken = srcCancel.Token; List <int> valList = new List <int>(elemCount / takeThCount + 100); barierStart.SignalAndWait(); try { while (!srcCancel.IsCancellationRequested) { int val = 0; val = col.Take(myToken); valList.Add(val); Thread.SpinWait(takeSpin); } } catch (OperationCanceledException) { } int val2 = 0; while (col.TryTake(out val2)) { valList.Add(val2); } barierTakers.SignalAndWait(); lock (globalList) { globalList.AddRange(valList); } }; for (int i = 0; i < addThreads.Length; i++) { addThreads[i] = new Thread(new ThreadStart(addAction)); } for (int i = 0; i < takeThreads.Length; i++) { takeThreads[i] = new Thread(new ThreadStart(takeAction)); } for (int i = 0; i < takeThreads.Length; i++) { takeThreads[i].Start(); } for (int i = 0; i < addThreads.Length; i++) { addThreads[i].Start(); } barierStart.SignalAndWait(); Stopwatch sw = Stopwatch.StartNew(); barierAdders.SignalAndWait(); srcCancel.Cancel(); barierTakers.SignalAndWait(); sw.Stop(); for (int i = 0; i < addThreads.Length; i++) { addThreads[i].Join(); } for (int i = 0; i < takeThreads.Length; i++) { takeThreads[i].Join(); } globalList.Sort(); if (globalList.Count != elemCount) { Console.WriteLine("Bad count"); } for (int i = 0; i < globalList.Count; i++) { if (globalList[i] != i) { Console.WriteLine("invalid elements"); break; } } if (name != null) { Console.WriteLine(name + ". LvlQ. Time = " + sw.ElapsedMilliseconds.ToString() + "ms"); } col.Dispose(); return(sw.Elapsed); }
// ========================== private void RunComplexTest(LevelingQueue <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 += 12; } 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]); } }
// ========================== private void PreserveOrderTest(LevelingQueue <int> queue, int elemCount) { Barrier bar = new Barrier(2); CancellationTokenSource cancelled = new CancellationTokenSource(); List <int> takenElems = new List <int>(elemCount + 1); Action addAction = () => { int curElem = 0; Random rnd = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId); bar.SignalAndWait(); while (curElem < elemCount) { if (rnd.Next(100) == 0) { queue.AddForced(curElem); } else { queue.Add(curElem); } if (rnd.Next(100) == 0) { Thread.Yield(); } SpinWaitHelper.SpinWait(rnd.Next(12)); curElem++; } cancelled.Cancel(); }; StringBuilder badInfo = new StringBuilder(); Action takeAction = () => { Random rnd = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId); bar.SignalAndWait(); try { while (!cancelled.IsCancellationRequested) { takenElems.Add(queue.Take(cancelled.Token)); //if (takenElems[takenElems.Count - 1] != takenElems.Count - 1) // badInfo.Append("Is taken from high = " + queue.LastTakeTop.ToString()); if (rnd.Next(100) == 0) { Thread.Yield(); } SpinWaitHelper.SpinWait(rnd.Next(12)); } } catch (OperationCanceledException) { } int item = 0; while (queue.TryTake(out item)) { takenElems.Add(item); } }; var sw = System.Diagnostics.Stopwatch.StartNew(); Task addTask = Task.Factory.StartNew(addAction, TaskCreationOptions.LongRunning); Task takeTask = Task.Factory.StartNew(takeAction, TaskCreationOptions.LongRunning); Task.WaitAll(addTask, takeTask); Assert.AreEqual(elemCount, takenElems.Count); for (int i = 0; i < takenElems.Count; i++) { if (i != takenElems[i]) { Assert.AreEqual(i, takenElems[i], $"i != takenElems[i], nextItem = {takenElems[i + 1]}, badInfo = '{badInfo}'"); } } }
// ========================= private void CancellationWorksTest(LevelingQueue <int> queue) { Barrier bar = new Barrier(2); CancellationTokenSource takeSource = new CancellationTokenSource(); int takeResult = 0; CancellationTokenSource peekSource = new CancellationTokenSource(); int peekResult = 0; CancellationTokenSource addSource = new CancellationTokenSource(); int addResult = 0; Task task = Task.Run(() => { bar.SignalAndWait(); int item = 0; try { AtomicSet(ref takeResult, queue.TryTake(out item, 60000, takeSource.Token)); } catch (OperationCanceledException) { Interlocked.Exchange(ref takeResult, 3); } try { AtomicSet(ref peekResult, queue.TryPeek(out item, 60000, peekSource.Token)); } catch (OperationCanceledException) { Interlocked.Exchange(ref peekResult, 3); } while (queue.TryAdd(-1)) { ; } if (queue.IsBackgroundTransferingEnabled) { queue.AddForced(-1); } try { AtomicSet(ref addResult, queue.TryAdd(100, 60000, addSource.Token)); } catch (OperationCanceledException) { Interlocked.Exchange(ref addResult, 3); } }); bar.SignalAndWait(); Thread.Sleep(10); Assert.AreEqual(0, takeResult); takeSource.Cancel(); TimingAssert.AreEqual(10000, 3, () => Volatile.Read(ref takeResult)); Thread.Sleep(10); Assert.AreEqual(0, peekResult); peekSource.Cancel(); TimingAssert.AreEqual(10000, 3, () => Volatile.Read(ref peekResult)); Thread.Sleep(10); Assert.AreEqual(0, addResult); addSource.Cancel(); TimingAssert.AreEqual(10000, 3, () => Volatile.Read(ref addResult)); task.Wait(); }
private void RunComplexTestOnCustom(int threadCount, int queueSize, int testElemCount, int addThreadCount, int procSpinWaitCount, int addSleepMs) { List <int> processedItems = new List <int>(testElemCount + 1); int currentItem = 0; Random rnd = new Random(); MemoryQueue <int> mem1 = new MemoryQueue <int>(100); MemoryQueue <int> mem2 = new MemoryQueue <int>(queueSize); LevelingQueue <int> lvl = new LevelingQueue <int>(mem1, mem2); using (DelegateQueueAsyncProcessor <int> proc = new DelegateQueueAsyncProcessor <int>(threadCount, lvl, "name", (elem, token) => { int curSpinCount = 0; lock (rnd) curSpinCount = rnd.Next(procSpinWaitCount); SpinWaitHelper.SpinWait(curSpinCount); lock (processedItems) processedItems.Add(elem); })) { Action addAction = () => { while (true) { int curVal = Interlocked.Increment(ref currentItem); if (curVal > testElemCount) { break; } proc.Add(curVal - 1); if (addSleepMs > 0) { SmartSleep(addSleepMs); } } }; Thread[] addThreads = new Thread[addThreadCount]; for (int i = 0; i < addThreads.Length; i++) { addThreads[i] = new Thread(new ThreadStart(addAction)); } for (int i = 0; i < addThreads.Length; i++) { addThreads[i].Start(); } proc.Start(); Assert.IsTrue(proc.IsWork); for (int i = 0; i < addThreads.Length; i++) { addThreads[i].Join(); } proc.Stop(true, true, true); Assert.AreEqual(testElemCount, processedItems.Count); processedItems.Sort(); for (int i = 0; i < processedItems.Count; i++) { Assert.AreEqual(i, processedItems[i]); } } }