public void TestEnqueueDequeueToTheLimit() { const int batchSize = 13; BlockingBatchingQueue <int> col = new BlockingBatchingQueue <int>(batchSize: batchSize, boundedCapacityInBatches: 2); for (int i = 0; i < batchSize * col.BoundedCapacityInBatches; i++) { Assert.IsTrue(col.TryAdd(i)); } Assert.IsFalse(col.TryAdd(int.MaxValue)); List <int> takenItems = new List <int>(); for (int i = 0; i < col.BoundedCapacityInBatches; i++) { Assert.IsTrue(col.TryTake(out int[] batch)); takenItems.AddRange(batch); } Assert.IsFalse(col.TryTake(out _)); for (int i = 0; i < takenItems.Count; i++) { Assert.AreEqual(i, takenItems[i]); } }
public void TestDisposeInterruptWaitersOnAdd() { BlockingBatchingQueue <int> queue = new BlockingBatchingQueue <int>(batchSize: 2, boundedCapacityInBatches: 1); queue.Add(1); queue.Add(2); Barrier bar = new Barrier(2); Task disposeTask = Task.Run(() => { bar.SignalAndWait(); Thread.Sleep(10); queue.Dispose(); }); try { bar.SignalAndWait(); bool added = queue.TryAdd(3, 10000); Assert.Fail(); } catch (OperationInterruptedException) { } catch (ObjectDisposedException) { } catch (Exception) { Assert.Fail("Unexpected exception"); } disposeTask.Wait(); }
public void TestTimeoutWorks() { const int batchSize = 17; BlockingBatchingQueue <int> queue = new BlockingBatchingQueue <int>(batchSize: batchSize, boundedCapacityInBatches: 8); Barrier bar = new Barrier(2); int takeResult = 0; int addResult = 0; Task task = Task.Run(() => { bar.SignalAndWait(); int[] item = null; if (queue.TryTake(out item, 100)) { Interlocked.Exchange(ref takeResult, 1); } else { Interlocked.Exchange(ref takeResult, 2); } while (queue.TryAdd(-1)) { ; } if (queue.TryAdd(100, 100)) { Interlocked.Exchange(ref addResult, 1); } else { Interlocked.Exchange(ref addResult, 2); } }); bar.SignalAndWait(); TimingAssert.AreEqual(10000, 2, () => Volatile.Read(ref takeResult), "take"); TimingAssert.AreEqual(10000, 2, () => Volatile.Read(ref addResult), "Add"); task.Wait(); }
private void SimpleConcurrentTestCore(int batchSize, int boundedCapacityInBatches) { BlockingBatchingQueue <long> col = new BlockingBatchingQueue <long>(batchSize: batchSize, boundedCapacityInBatches: boundedCapacityInBatches); Barrier bar = new Barrier(4); CancellationTokenSource cancelToken = new CancellationTokenSource(); List <long> takenItems = new List <long>(); Task addTask = Task.Run(() => { Random rnd = new Random(); bar.SignalAndWait(); long data = 0; while (!cancelToken.IsCancellationRequested) { if (col.TryAdd(data)) { data++; } if (rnd.Next(100) == 1) { col.CompleteCurrentBatch(); } } }); Task takeTask = Task.Run(() => { bar.SignalAndWait(); while (!cancelToken.IsCancellationRequested) { if (col.TryTake(out long[] itemsT)) { takenItems.AddRange(itemsT); } if (takenItems.Count > int.MaxValue / 2) { cancelToken.Cancel(); } } }); Task enumerateTask = Task.Run(() => { bar.SignalAndWait(); while (!cancelToken.IsCancellationRequested) { int count = 0; long prevItem = -1; foreach (long item in col) { count++; if (prevItem > 0) { Assert.AreEqual(prevItem + 1, item); } prevItem = item; } Thread.Sleep(count > 100 ? 0 : 1); } }); bar.SignalAndWait(); Thread.Sleep(300); cancelToken.Cancel(); Task.WaitAll(addTask, takeTask, enumerateTask); while (col.TryTake(out long[] itemsF)) { takenItems.AddRange(itemsF); } col.CompleteCurrentBatch(); if (col.TryTake(out long[] itemsFF)) { takenItems.AddRange(itemsFF); } for (int i = 0; i < takenItems.Count; i++) { Assert.AreEqual(i, takenItems[i]); } }