public void TestAddTake() { SparceArrayStorage <PoolElementWrapper <int> > storage = CreateSparceArray(100); IndexedStackElementStorage <int> testInst = new IndexedStackElementStorage <int>(storage); try { Assert.IsTrue(testInst.HeadIndex < 0); for (int i = 0; i < storage.Count; i++) { testInst.Add(storage.RawData[i]); } Assert.IsTrue(testInst.HeadIndex == 99); for (int i = storage.Count - 1; i >= 0; i--) { PoolElementWrapper <int> elem = null; bool takeResult = testInst.TryTake(out elem); Assert.IsTrue(takeResult); Assert.AreEqual(i, elem.Element); } PoolElementWrapper <int> elem2 = null; Assert.IsFalse(testInst.TryTake(out elem2)); } finally { DestroySparceArray(storage); } }
public void TestConcurrentAddTake() { SparceArrayStorage <PoolElementWrapper <int> > storage = CreateSparceArray(1000); IndexedStackElementStorage <int> testInst = new IndexedStackElementStorage <int>(storage); try { RunComplexTest(storage, testInst, 5000000, 1 + Environment.ProcessorCount / 2); } finally { DestroySparceArray(storage); } }
private void RunComplexTest(SparceArrayStorage <PoolElementWrapper <int> > storage, IndexedStackElementStorage <int> stack, 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(); BlockingCollection <PoolElementWrapper <int> > freeElements = new BlockingCollection <PoolElementWrapper <int> >(); foreach (var elem in storage.RawData) { if (elem != null) { freeElements.Add(elem); } } int[] addedCountArray = new int[storage.Count]; int[] takenCountArray = new int[storage.Count]; 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; } var elem = freeElements.Take(); stack.Add(elem); Interlocked.Increment(ref addedCountArray[storage.IndexOf(elem)]); int sleepTime = rnd.Next(100); if (sleepTime > 0) { Thread.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) { PoolElementWrapper <int> tmp = null; if (stack.TryTake(out tmp)) { freeElements.Add(tmp); Interlocked.Increment(ref takenCountArray[storage.IndexOf(tmp)]); } int sleepTime = rnd.Next(100); if (sleepTime > 0) { Thread.SpinWait(sleepTime); } } } catch (OperationCanceledException) { } PoolElementWrapper <int> tmp2 = null; while (stack.TryTake(out tmp2)) { freeElements.Add(tmp2); Interlocked.Increment(ref takenCountArray[storage.IndexOf(tmp2)]); } }; 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(storage.Count, freeElements.Count); Assert.IsTrue(stack.HeadIndex < 0); for (int i = 0; i < storage.Count; i++) { Assert.IsTrue(addedCountArray[i] == takenCountArray[i], "Added count != taken count"); } }