public void TestSingleAddSteal() { ThreadPoolLocalQueue q = new ThreadPoolLocalQueue(); Assert.IsTrue(q.TryAddLocal(new TestThreadPoolItem(1))); ThreadPoolWorkItem item = null; Assert.IsTrue(q.TrySteal(out item)); Assert.IsNotNull(item); Assert2.AreEqual(1, item); }
private void RunLocalThreadQueueAddStealTest(ThreadPoolLocalQueue q, int elemCount, int fillFactor) { Random rnd = new Random(); int addElem = 0; int takeElem = 0; List <int> takenIndexes = new List <int>(elemCount + 1); while (takeElem < elemCount) { int addCount = rnd.Next(fillFactor); for (int i = 0; i < addCount; i++) { if (addElem >= elemCount || !q.TryAddLocal(new TestThreadPoolItem(addElem))) { break; } addElem++; } int removeCount = rnd.Next(fillFactor); for (int i = 0; i < removeCount; i++) { ThreadPoolWorkItem tmp = null; if (!q.TrySteal(out tmp)) { break; } Assert.IsNotNull(tmp); takenIndexes.Add((TestThreadPoolItem)tmp); takeElem++; } } Assert.AreEqual(elemCount, takenIndexes.Count); takenIndexes.Sort(); for (int i = 0; i < elemCount; i++) { Assert.AreEqual(i, takenIndexes[i]); } }
public void TestAddStealUpToTheLimit() { ThreadPoolLocalQueue q = new ThreadPoolLocalQueue(); int index = 0; while (q.TryAddLocal(new TestThreadPoolItem(index))) { index++; Assert.IsTrue(index < int.MaxValue); } int index2 = 0; ThreadPoolWorkItem item = null; while (q.TrySteal(out item)) { Assert.IsNotNull(item); Assert.IsTrue((TestThreadPoolItem)item == index2++); } Assert.AreEqual(index, index2); }
private void RunLocalThreadQueuePrimaryScenario(ThreadPoolLocalQueue q, int elemCount, int slealThCount, int fillFactor) { int trackElemCount = elemCount; int addFinished = 0; int atomicRandom = 0; Thread mainThread = null; Thread[] stealThreads = new Thread[slealThCount]; List <int> global = new List <int>(elemCount + 1); Action mainAction = () => { List <int> data = new List <int>(elemCount); Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * slealThCount); while (Volatile.Read(ref trackElemCount) >= 0) { int addCount = fillFactor; if (rnd != null) { addCount = rnd.Next(fillFactor); } for (int i = 0; i < addCount; i++) { int item = --trackElemCount; if (item < 0) { break; } if (!q.TryAddLocal(new TestThreadPoolItem(item))) { ++trackElemCount; break; } } int removeCount = rnd.Next(fillFactor); for (int i = 0; i < removeCount; i++) { ThreadPoolWorkItem item = null; if (!q.TryTakeLocal(out item)) { break; } data.Add((TestThreadPoolItem)item); } } Interlocked.Increment(ref addFinished); ThreadPoolWorkItem finalItem = null; while (q.TryTakeLocal(out finalItem)) { data.Add((TestThreadPoolItem)finalItem); } lock (global) global.AddRange(data); }; Action stealAction = () => { Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * slealThCount); List <int> data = new List <int>(); while (Volatile.Read(ref addFinished) < 1 && Volatile.Read(ref trackElemCount) > elemCount / 1000) { ThreadPoolWorkItem tmp; if (q.TrySteal(out tmp)) { data.Add((TestThreadPoolItem)tmp); } int sleepTime = rnd.Next(5) - 3; if (sleepTime > 0) { Thread.Sleep(sleepTime); } } lock (global) global.AddRange(data); }; mainThread = new Thread(new ThreadStart(mainAction)); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i] = new Thread(new ThreadStart(stealAction)); } mainThread.Start(); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i].Start(); } mainThread.Join(); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i].Join(); } Assert.AreEqual(elemCount, global.Count, "Incorrect element count"); global.Sort(); for (int i = 0; i < elemCount; i++) { Assert.AreEqual(i, global[i], "Incorrect data"); } }
private static bool TestLocalThreadQueuePrimaryScenario(ThreadPoolLocalQueue q, int elemCount, int slealThCount, int fillFactor, bool useRandom) { int trackElemCount = elemCount; int addFinished = 0; int atomicRandom = 0; Thread mainThread = null; Thread[] stealThreads = new Thread[slealThCount]; List <int> global = new List <int>(elemCount); Action mainAction = () => { List <int> data = new List <int>(elemCount); Random rnd = null; if (useRandom) { rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * slealThCount); } while (Volatile.Read(ref trackElemCount) >= 0) { int addCount = fillFactor; if (rnd != null) { addCount = rnd.Next(fillFactor); } for (int i = 0; i < addCount; i++) { int item = --trackElemCount; if (item < 0) { break; } if (!q.TryAddLocal(new TestThreadPoolItem(item))) { ++trackElemCount; break; } } int removeCount = fillFactor; if (rnd != null) { removeCount = rnd.Next(fillFactor); } for (int i = 0; i < removeCount; i++) { ThreadPoolWorkItem item = null; if (!q.TryTakeLocal(out item)) { break; } data.Add((TestThreadPoolItem)item); } } Interlocked.Increment(ref addFinished); ThreadPoolWorkItem finalItem = null; while (q.TryTakeLocal(out finalItem)) { data.Add((TestThreadPoolItem)finalItem); } lock (global) global.AddRange(data); }; Action stealAction = () => { Random rnd = null; if (useRandom) { rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * slealThCount); } List <int> data = new List <int>(); while (Volatile.Read(ref addFinished) < 1 && Volatile.Read(ref trackElemCount) > elemCount / 1000) { ThreadPoolWorkItem tmp; if (q.TrySteal(out tmp)) { data.Add((TestThreadPoolItem)tmp); } int sleepTime = Volatile.Read(ref trackElemCount) % 2; if (rnd != null) { sleepTime = rnd.Next(2); } if (sleepTime > 0) { Thread.Sleep(sleepTime); } } lock (global) global.AddRange(data); }; mainThread = new Thread(new ThreadStart(mainAction)); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i] = new Thread(new ThreadStart(stealAction)); } Stopwatch sw = Stopwatch.StartNew(); mainThread.Start(); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i].Start(); } mainThread.Join(); for (int i = 0; i < stealThreads.Length; i++) { stealThreads[i].Join(); } sw.Stop(); bool result = true; global.Sort(); if (global.Count != elemCount) { result = false; Console.WriteLine("Incorrect element count"); } HashSet <int> set = new HashSet <int>(global); if (set.Count != global.Count) { result = false; Console.WriteLine("Incorrect distinct element count"); } for (int i = 0; i < Math.Min(elemCount, global.Count); i++) { if (global[i] != i) { result = false; Console.WriteLine("Incorrect data"); break; } } Console.WriteLine("PrimaryScenario " + q.GetType().Name + ". Element count = " + elemCount.ToString() + ", Time = " + sw.ElapsedMilliseconds.ToString() + "ms"); Console.WriteLine(); return(result); }