public void TestBoundaryContraction() { BlockingQueue <int> col = new BlockingQueue <int>(110); Assert.AreEqual(110, col.BoundedCapacity); for (int i = 0; i < 100; i++) { col.Add(i); } col.DecreaseBoundedCapacity(10); Assert.AreEqual(100, col.BoundedCapacity); Assert.IsFalse(col.TryAdd(int.MaxValue)); col.DecreaseBoundedCapacity(10); Assert.AreEqual(90, col.BoundedCapacity); Assert.AreEqual(100, col.Count); Assert.IsFalse(col.TryAdd(int.MaxValue)); for (int i = 0; i < 10; i++) { Assert.AreEqual(i, col.Take()); Assert.IsFalse(col.TryAdd(int.MaxValue)); } Assert.AreEqual(90, col.BoundedCapacity); Assert.AreEqual(90, col.Count); for (int i = 10; i < 100; i++) { Assert.AreEqual(i, col.Take()); } }
private void RunComplexTest(BlockingQueue <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(100); int tmpItem = 0; if (q.TryPeek(out tmpItem) && tmpItem == item) { sleepTime += 100; } if (sleepTime > 0) { Thread.SpinWait(sleepTime); } if (rnd.Next(100) == 0) { q.IncreaseBoundedCapacity(1); } if (rnd.Next(100) == 0 && q.BoundedCapacity > 20) { q.DecreaseBoundedCapacity(1); } } 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(100); if (sleepTime > 0) { Thread.SpinWait(sleepTime); } } } catch (OperationCanceledException) { } int tmp2; while (q.TryTake(out tmp2)) { data.Add((int)tmp2); } lock (global) global.AddRange(data); }; Task.Delay(1000).ContinueWith(t => q.IncreaseBoundedCapacity(50)); 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]); } }