Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@
<data name="ConcurrentBag_CopyTo_ArgumentNullException" xml:space="preserve">
<value>The array argument is null.</value>
</data>
<data name="ConcurrentBag_CopyTo_ArgumentOutOfRangeException" xml:space="preserve">
<data name="Collection_CopyTo_ArgumentOutOfRangeException" xml:space="preserve">
<value>The index argument must be greater than or equal zero.</value>
</data>
<data name="ConcurrentCollection_SyncRoot_NotSupported" xml:space="preserve">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ public void CopyTo(T[] array, int index)
}
if (index < 0)
{
throw new ArgumentOutOfRangeException(nameof(index), SR.ConcurrentBag_CopyTo_ArgumentOutOfRangeException);
throw new ArgumentOutOfRangeException(nameof(index), SR.Collection_CopyTo_ArgumentOutOfRangeException);
}

// Short path if the bag is empty
Expand Down

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/System.Collections.Concurrent/tests/ConcurrentBagTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ namespace System.Collections.Concurrent.Tests
public class ConcurrentBagTests : ProducerConsumerCollectionTests
{
protected override bool Enumerator_Current_UndefinedOperation_Throws => true;
protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection() => new ConcurrentBag<int>();
protected override IProducerConsumerCollection<T> CreateProducerConsumerCollection<T>() => new ConcurrentBag<T>();
protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection(IEnumerable<int> collection) => new ConcurrentBag<int>(collection);
protected override bool IsEmpty(IProducerConsumerCollection<int> pcc) => ((ConcurrentBag<int>)pcc).IsEmpty;
protected override bool TryPeek(IProducerConsumerCollection<int> pcc, out int result) => ((ConcurrentBag<int>)pcc).TryPeek(out result);
protected override bool TryPeek<T>(IProducerConsumerCollection<T> pcc, out T result) => ((ConcurrentBag<T>)pcc).TryPeek(out result);
protected override IProducerConsumerCollection<int> CreateOracle(IEnumerable<int> collection) => new BagOracle(collection);

[Theory]
Expand Down
62 changes: 52 additions & 10 deletions src/System.Collections.Concurrent/tests/ConcurrentQueueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ namespace System.Collections.Concurrent.Tests
{
public class ConcurrentQueueTests : ProducerConsumerCollectionTests
{
protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection() => new ConcurrentQueue<int>();
protected override IProducerConsumerCollection<T> CreateProducerConsumerCollection<T>() => new ConcurrentQueue<T>();
protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection(IEnumerable<int> collection) => new ConcurrentQueue<int>(collection);
protected override bool IsEmpty(IProducerConsumerCollection<int> pcc) => ((ConcurrentQueue<int>)pcc).IsEmpty;
protected override bool TryPeek(IProducerConsumerCollection<int> pcc, out int result) => ((ConcurrentQueue<int>)pcc).TryPeek(out result);
protected override bool TryPeek<T>(IProducerConsumerCollection<T> pcc, out T result) => ((ConcurrentQueue<T>)pcc).TryPeek(out result);
protected override bool ResetImplemented => false;
protected override bool IEnumerable_Generic_Enumerator_Current_EnumerationNotStarted_ThrowsInvalidOperationException => false;
protected override IProducerConsumerCollection<int> CreateOracle(IEnumerable<int> collection) => new QueueOracle(collection);
Expand Down Expand Up @@ -186,14 +186,6 @@ public void CopyTo_AllItemsCopiedAtCorrectLocation(int count, bool viaInterface)
}
}

[Fact]
public void ICollection_CopyTo_InvalidArg_ThrowsException()
{
Assert.Throws<ArgumentNullException>(() => ((ICollection)new ConcurrentQueue<int>()).CopyTo(null, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => ((ICollection)new ConcurrentQueue<int>()).CopyTo(new int[0], -1));
Assert.Throws<ArgumentException>(() => ((ICollection)new ConcurrentQueue<int>()).CopyTo(new int[0], 1));
}

[Fact]
public void IEnumerable_GetAllExpectedItems()
{
Expand Down Expand Up @@ -253,6 +245,56 @@ public void ReferenceTypes_NulledAfterDequeue()
GC.KeepAlive(queue);
}

[Fact]
public void ManySegments_ConcurrentDequeues_RemainsConsistent()
{
var cq = new ConcurrentQueue<int>();
const int Iters = 10000;

for (int i = 0; i < Iters; i++)
{
cq.Enqueue(i);
cq.GetEnumerator().Dispose(); // force new segment
}

int dequeues = 0;
Parallel.For(0, Environment.ProcessorCount, i =>
{
while (!cq.IsEmpty)
{
int item;
if (cq.TryDequeue(out item))
{
Interlocked.Increment(ref dequeues);
}
}
});

Assert.Equal(0, cq.Count);
Assert.True(cq.IsEmpty);
Assert.Equal(Iters, dequeues);
}

[Fact]
public void ManySegments_ConcurrentEnqueues_RemainsConsistent()
{
var cq = new ConcurrentQueue<int>();
const int ItemsPerThread = 1000;
int threads = Environment.ProcessorCount;

Parallel.For(0, threads, i =>
{
for (int item = 0; item < ItemsPerThread; item++)
{
cq.Enqueue(item + (i * ItemsPerThread));
cq.GetEnumerator().Dispose();
}
});

Assert.Equal(ItemsPerThread * threads, cq.Count);
Assert.Equal(Enumerable.Range(0, ItemsPerThread * threads), cq.OrderBy(i => i));
}

/// <summary>Sets an event when finalized.</summary>
private sealed class Finalizable
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ namespace System.Collections.Concurrent.Tests
{
public class ConcurrentStackTests : ProducerConsumerCollectionTests
{
protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection() => new ConcurrentStack<int>();
protected override IProducerConsumerCollection<T> CreateProducerConsumerCollection<T>() => new ConcurrentStack<T>();
protected override IProducerConsumerCollection<int> CreateProducerConsumerCollection(IEnumerable<int> collection) => new ConcurrentStack<int>(collection);
protected override bool IsEmpty(IProducerConsumerCollection<int> pcc) => ((ConcurrentStack<int>)pcc).IsEmpty;
protected override bool TryPeek(IProducerConsumerCollection<int> pcc, out int result) => ((ConcurrentStack<int>)pcc).TryPeek(out result);
protected override bool TryPeek<T>(IProducerConsumerCollection<T> pcc, out T result) => ((ConcurrentStack<T>)pcc).TryPeek(out result);
protected override IProducerConsumerCollection<int> CreateOracle(IEnumerable<int> collection) => new StackOracle(collection);
protected override bool ResetImplemented => false;
protected override bool IEnumerable_Generic_Enumerator_Current_EnumerationNotStarted_ThrowsInvalidOperationException => false;
Expand Down
Loading