summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs')
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs323
1 files changed, 1 insertions, 322 deletions
diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs
index c36d96c26c..10a5201f6c 100644
--- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs
+++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs
@@ -20,7 +20,6 @@ using System.Diagnostics.Contracts;
using System.Runtime.ConstrainedExecution;
using System.Runtime.Serialization;
using System.Security;
-using System.Security.Permissions;
using System.Threading;
namespace System.Collections.Concurrent
@@ -45,7 +44,7 @@ namespace System.Collections.Concurrent
/// </remarks>
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))]
- public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
+ internal class ConcurrentStack<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
{
/// <summary>
/// A simple (internal) node type used to store elements of concurrent stacks and queues.
@@ -79,61 +78,6 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Initializes a new instance of the <see cref="ConcurrentStack{T}"/>
- /// class that contains elements copied from the specified collection
- /// </summary>
- /// <param name="collection">The collection whose elements are copied to the new <see
- /// cref="ConcurrentStack{T}"/>.</param>
- /// <exception cref="T:System.ArgumentNullException">The <paramref name="collection"/> argument is
- /// null.</exception>
- public ConcurrentStack(IEnumerable<T> collection)
- {
- if (collection == null)
- {
- throw new ArgumentNullException(nameof(collection));
- }
- InitializeFromCollection(collection);
- }
-
- /// <summary>
- /// Initializes the contents of the stack from an existing collection.
- /// </summary>
- /// <param name="collection">A collection from which to copy elements.</param>
- private void InitializeFromCollection(IEnumerable<T> collection)
- {
- // We just copy the contents of the collection to our stack.
- Node lastNode = null;
- foreach (T element in collection)
- {
- Node newNode = new Node(element);
- newNode.m_next = lastNode;
- lastNode = newNode;
- }
-
- m_head = lastNode;
- }
-
- /// <summary>
- /// Gets a value that indicates whether the <see cref="ConcurrentStack{T}"/> is empty.
- /// </summary>
- /// <value>true if the <see cref="ConcurrentStack{T}"/> is empty; otherwise, false.</value>
- /// <remarks>
- /// For determining whether the collection contains any items, use of this property is recommended
- /// rather than retrieving the number of items from the <see cref="Count"/> property and comparing it
- /// to 0. However, as this collection is intended to be accessed concurrently, it may be the case
- /// that another thread will modify the collection after <see cref="IsEmpty"/> returns, thus invalidating
- /// the result.
- /// </remarks>
- public bool IsEmpty
- {
- // Checks whether the stack is empty. Clearly the answer may be out of date even prior to
- // the function returning (i.e. if another thread concurrently adds to the stack). It does
- // guarantee, however, that, if another thread does not mutate the stack, a subsequent call
- // to TryPop will return true -- i.e. it will also read the stack as non-empty.
- get { return m_head == null; }
- }
-
- /// <summary>
/// Gets the number of elements contained in the <see cref="ConcurrentStack{T}"/>.
/// </summary>
/// <value>The number of elements contained in the <see cref="ConcurrentStack{T}"/>.</value>
@@ -196,18 +140,6 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Removes all objects from the <see cref="ConcurrentStack{T}"/>.
- /// </summary>
- public void Clear()
- {
- // Clear the list by setting the head to null. We don't need to use an atomic
- // operation for this: anybody who is mutating the head by pushing or popping
- // will need to use an atomic operation to guarantee they serialize and don't
- // overwrite our setting of the head to null.
- m_head = null;
- }
-
- /// <summary>
/// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see
/// cref="T:System.Array"/>, starting at a particular
/// <see cref="T:System.Array"/> index.
@@ -306,79 +238,6 @@ namespace System.Collections.Concurrent
PushCore(newNode, newNode);
}
- /// <summary>
- /// Inserts multiple objects at the top of the <see cref="ConcurrentStack{T}"/> atomically.
- /// </summary>
- /// <param name="items">The objects to push onto the <see cref="ConcurrentStack{T}"/>.</param>
- /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference
- /// (Nothing in Visual Basic).</exception>
- /// <remarks>
- /// When adding multiple items to the stack, using PushRange is a more efficient
- /// mechanism than using <see cref="Push"/> one item at a time. Additionally, PushRange
- /// guarantees that all of the elements will be added atomically, meaning that no other threads will
- /// be able to inject elements between the elements being pushed. Items at lower indices in
- /// the <paramref name="items"/> array will be pushed before items at higher indices.
- /// </remarks>
- public void PushRange(T[] items)
- {
- if (items == null)
- {
- throw new ArgumentNullException(nameof(items));
- }
- PushRange(items, 0, items.Length);
- }
-
- /// <summary>
- /// Inserts multiple objects at the top of the <see cref="ConcurrentStack{T}"/> atomically.
- /// </summary>
- /// <param name="items">The objects to push onto the <see cref="ConcurrentStack{T}"/>.</param>
- /// <param name="startIndex">The zero-based offset in <paramref name="items"/> at which to begin
- /// inserting elements onto the top of the <see cref="ConcurrentStack{T}"/>.</param>
- /// <param name="count">The number of elements to be inserted onto the top of the <see
- /// cref="ConcurrentStack{T}"/>.</param>
- /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference
- /// (Nothing in Visual Basic).</exception>
- /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref
- /// name="count"/> is negative. Or <paramref name="startIndex"/> is greater than or equal to the length
- /// of <paramref name="items"/>.</exception>
- /// <exception cref="ArgumentException"><paramref name="startIndex"/> + <paramref name="count"/> is
- /// greater than the length of <paramref name="items"/>.</exception>
- /// <remarks>
- /// When adding multiple items to the stack, using PushRange is a more efficient
- /// mechanism than using <see cref="Push"/> one item at a time. Additionally, PushRange
- /// guarantees that all of the elements will be added atomically, meaning that no other threads will
- /// be able to inject elements between the elements being pushed. Items at lower indices in the
- /// <paramref name="items"/> array will be pushed before items at higher indices.
- /// </remarks>
- public void PushRange(T[] items, int startIndex, int count)
- {
- ValidatePushPopRangeInput(items, startIndex, count);
-
- // No op if the count is zero
- if (count == 0)
- return;
-
-
- Node head, tail;
- head = tail = new Node(items[startIndex]);
- for (int i = startIndex + 1; i < startIndex + count; i++)
- {
- Node node = new Node(items[i]);
- node.m_next = head;
- head = node;
- }
-
- tail.m_next = m_head;
- if (Interlocked.CompareExchange(ref m_head, head, tail.m_next) == tail.m_next)
- {
- return;
- }
-
- // If we failed, go to the slow path and loop around until we succeed.
- PushCore(head, tail);
-
- }
-
/// <summary>
/// Push one or many nodes into the stack, if head and tails are equal then push one node to the stack other wise push the list between head
@@ -402,73 +261,6 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Local helper function to validate the Pop Push range methods input
- /// </summary>
- private void ValidatePushPopRangeInput(T[] items, int startIndex, int count)
- {
- if (items == null)
- {
- throw new ArgumentNullException(nameof(items));
- }
- if (count < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ConcurrentStack_PushPopRange_CountOutOfRange"));
- }
- int length = items.Length;
- if (startIndex >= length || startIndex < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ConcurrentStack_PushPopRange_StartOutOfRange"));
- }
- if (length - count < startIndex) //instead of (startIndex + count > items.Length) to prevent overflow
- {
- throw new ArgumentException(Environment.GetResourceString("ConcurrentStack_PushPopRange_InvalidCount"));
- }
- }
-
- /// <summary>
- /// Attempts to add an object to the <see
- /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
- /// </summary>
- /// <param name="item">The object to add to the <see
- /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null
- /// reference (Nothing in Visual Basic) for reference types.
- /// </param>
- /// <returns>true if the object was added successfully; otherwise, false.</returns>
- /// <remarks>For <see cref="ConcurrentStack{T}"/>, this operation
- /// will always insert the object onto the top of the <see cref="ConcurrentStack{T}"/>
- /// and return true.</remarks>
- bool IProducerConsumerCollection<T>.TryAdd(T item)
- {
- Push(item);
- return true;
- }
-
- /// <summary>
- /// Attempts to return an object from the top of the <see cref="ConcurrentStack{T}"/>
- /// without removing it.
- /// </summary>
- /// <param name="result">When this method returns, <paramref name="result"/> contains an object from
- /// the top of the <see cref="T:System.Collections.Concurrent.ConccurrentStack{T}"/> or an
- /// unspecified value if the operation failed.</param>
- /// <returns>true if and object was returned successfully; otherwise, false.</returns>
- public bool TryPeek(out T result)
- {
- Node head = m_head;
-
- // If the stack is empty, return false; else return the element and true.
- if (head == null)
- {
- result = default(T);
- return false;
- }
- else
- {
- result = head.m_value;
- return true;
- }
- }
-
- /// <summary>
/// Attempts to pop and return the object at the top of the <see cref="ConcurrentStack{T}"/>.
/// </summary>
/// <param name="result">
@@ -498,83 +290,6 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Attempts to pop and return multiple objects from the top of the <see cref="ConcurrentStack{T}"/>
- /// atomically.
- /// </summary>
- /// <param name="items">
- /// The <see cref="T:System.Array"/> to which objects popped from the top of the <see
- /// cref="ConcurrentStack{T}"/> will be added.
- /// </param>
- /// <returns>The number of objects successfully popped from the top of the <see
- /// cref="ConcurrentStack{T}"/> and inserted in
- /// <paramref name="items"/>.</returns>
- /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null argument (Nothing
- /// in Visual Basic).</exception>
- /// <remarks>
- /// When popping multiple items, if there is little contention on the stack, using
- /// TryPopRange can be more efficient than using <see cref="TryPop"/>
- /// once per item to be removed. Nodes fill the <paramref name="items"/>
- /// with the first node to be popped at the startIndex, the second node to be popped
- /// at startIndex + 1, and so on.
- /// </remarks>
- public int TryPopRange(T[] items)
- {
- if (items == null)
- {
- throw new ArgumentNullException(nameof(items));
- }
-
- return TryPopRange(items, 0, items.Length);
- }
-
- /// <summary>
- /// Attempts to pop and return multiple objects from the top of the <see cref="ConcurrentStack{T}"/>
- /// atomically.
- /// </summary>
- /// <param name="items">
- /// The <see cref="T:System.Array"/> to which objects popped from the top of the <see
- /// cref="ConcurrentStack{T}"/> will be added.
- /// </param>
- /// <param name="startIndex">The zero-based offset in <paramref name="items"/> at which to begin
- /// inserting elements from the top of the <see cref="ConcurrentStack{T}"/>.</param>
- /// <param name="count">The number of elements to be popped from top of the <see
- /// cref="ConcurrentStack{T}"/> and inserted into <paramref name="items"/>.</param>
- /// <returns>The number of objects successfully popped from the top of
- /// the <see cref="ConcurrentStack{T}"/> and inserted in <paramref name="items"/>.</returns>
- /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference
- /// (Nothing in Visual Basic).</exception>
- /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref
- /// name="count"/> is negative. Or <paramref name="startIndex"/> is greater than or equal to the length
- /// of <paramref name="items"/>.</exception>
- /// <exception cref="ArgumentException"><paramref name="startIndex"/> + <paramref name="count"/> is
- /// greater than the length of <paramref name="items"/>.</exception>
- /// <remarks>
- /// When popping multiple items, if there is little contention on the stack, using
- /// TryPopRange can be more efficient than using <see cref="TryPop"/>
- /// once per item to be removed. Nodes fill the <paramref name="items"/>
- /// with the first node to be popped at the startIndex, the second node to be popped
- /// at startIndex + 1, and so on.
- /// </remarks>
- public int TryPopRange(T[] items, int startIndex, int count)
- {
- ValidatePushPopRangeInput(items, startIndex, count);
-
- // No op if the count is zero
- if (count == 0)
- return 0;
-
- Node poppedHead;
- int nodesCount = TryPopCore(count, out poppedHead);
- if (nodesCount > 0)
- {
- CopyRemovedItems(poppedHead, items, startIndex, nodesCount);
-
- }
- return nodesCount;
-
- }
-
- /// <summary>
/// Local helper function to Pop an item from the stack, slow path
/// </summary>
/// <param name="result">The popped item</param>
@@ -648,42 +363,6 @@ namespace System.Collections.Concurrent
}
}
-
- /// <summary>
- /// Local helper function to copy the poped elements into a given collection
- /// </summary>
- /// <param name="head">The head of the list to be copied</param>
- /// <param name="collection">The collection to place the popped items in</param>
- /// <param name="startIndex">the beginning of index of where to place the popped items</param>
- /// <param name="nodesCount">The number of nodes.</param>
- private void CopyRemovedItems(Node head, T[] collection, int startIndex, int nodesCount)
- {
- Node current = head;
- for (int i = startIndex; i < startIndex + nodesCount; i++)
- {
- collection[i] = current.m_value;
- current = current.m_next;
- }
-
- }
-
- /// <summary>
- /// Attempts to remove and return an object from the <see
- /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
- /// </summary>
- /// <param name="item">
- /// When this method returns, if the operation was successful, <paramref name="item"/> contains the
- /// object removed. If no object was available to be removed, the value is unspecified.
- /// </param>
- /// <returns>true if an element was removed and returned succesfully; otherwise, false.</returns>
- /// <remarks>For <see cref="ConcurrentStack{T}"/>, this operation will attempt to pope the object at
- /// the top of the <see cref="ConcurrentStack{T}"/>.
- /// </remarks>
- bool IProducerConsumerCollection<T>.TryTake(out T item)
- {
- return TryPop(out item);
- }
-
/// <summary>
/// Copies the items stored in the <see cref="ConcurrentStack{T}"/> to a new array.
/// </summary>