// ConcurrentStack.cs
//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
// Copyright (c) 2008 Jérémie "Garuma" Laval
+// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
namespace System.Collections.Concurrent
{
-
+ [System.Diagnostics.DebuggerDisplay ("Count = {Count}")]
+ [System.Diagnostics.DebuggerTypeProxy (typeof (CollectionDebuggerView<>))]
public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IEnumerable<T>,
ICollection, IEnumerable
{
class Node
{
public T Value = default (T);
- public Node Next = null;
+ public Node Next;
}
- Node head = null;
+ Node head;
int count;
{
}
- public ConcurrentStack (IEnumerable<T> enumerable)
+ public ConcurrentStack (IEnumerable<T> collection)
{
- foreach (T item in enumerable)
+ if (collection == null)
+ throw new ArgumentNullException ("collection");
+
+ foreach (T item in collection)
Push (item);
}
return true;
}
- public void Push (T element)
+ public void Push (T item)
{
Node temp = new Node ();
- temp.Value = element;
+ temp.Value = item;
do {
temp.Next = head;
} while (Interlocked.CompareExchange (ref head, temp, temp.Next) != temp.Next);
Interlocked.Increment (ref count);
}
- public void PushRange (T[] values)
+ public void PushRange (T[] items)
{
- PushRange (values, 0, values.Length);
+ if (items == null)
+ throw new ArgumentNullException ("items");
+
+ PushRange (items, 0, items.Length);
}
- public void PushRange (T[] values, int start, int length)
+ public void PushRange (T[] items, int startIndex, int count)
{
+ RangeArgumentsCheck (items, startIndex, count);
+
Node insert = null;
Node first = null;
- for (int i = start; i < length; i++) {
+ for (int i = startIndex; i < count; i++) {
Node temp = new Node ();
- temp.Value = values[i];
+ temp.Value = items[i];
temp.Next = insert;
insert = temp;
first.Next = head;
} while (Interlocked.CompareExchange (ref head, insert, first.Next) != first.Next);
- Interlocked.Add (ref count, length);
+ Interlocked.Add (ref count, count);
}
- public bool TryPop (out T value)
+ public bool TryPop (out T result)
{
Node temp;
do {
temp = head;
// The stak is empty
if (temp == null) {
- value = default (T);
+ result = default (T);
return false;
}
} while (Interlocked.CompareExchange (ref head, temp.Next, temp) != temp);
Interlocked.Decrement (ref count);
- value = temp.Value;
+ result = temp.Value;
+
return true;
}
- public int TryPopRange (T[] values)
+ public int TryPopRange (T[] items)
{
- return TryPopRange (values, 0, values.Length);
+ if (items == null)
+ throw new ArgumentNullException ("items");
+ return TryPopRange (items, 0, items.Length);
}
- public int TryPopRange (T[] values, int startIndex, int count)
+ public int TryPopRange (T[] items, int startIndex, int count)
{
+ RangeArgumentsCheck (items, startIndex, count);
+
Node temp;
Node end;
do {
temp = head;
if (temp == null)
- return -1;
+ return 0;
end = temp;
- for (int j = 0; j < count - 1; j++) {
+ for (int j = 0; j < count; j++) {
end = end.Next;
if (end == null)
break;
} while (Interlocked.CompareExchange (ref head, end, temp) != temp);
int i;
- for (i = startIndex; i < count && temp != null; i++) {
- values[i] = temp.Value;
+ for (i = startIndex; i < startIndex + count && temp != null; i++) {
+ items[i] = temp.Value;
+ end = temp;
temp = temp.Next;
}
+ Interlocked.Add (ref this.count, -(i - startIndex));
- return i - 1;
+ return i - startIndex;
}
- public bool TryPeek (out T value)
+ public bool TryPeek (out T result)
{
Node myHead = head;
if (myHead == null) {
- value = default (T);
+ result = default (T);
return false;
}
- value = myHead.Value;
+ result = myHead.Value;
return true;
}
void ICollection.CopyTo (Array array, int index)
{
- T[] dest = array as T[];
- if (dest == null)
- return;
- CopyTo (dest, index);
+ ICollection ic = new List<T> (this);
+ ic.CopyTo (array, index);
}
- public void CopyTo (T[] dest, int index)
+ public void CopyTo (T[] array, int index)
{
+ if (array == null)
+ throw new ArgumentNullException ("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException ("index");
+ if (index > array.Length)
+ throw new ArgumentException ("index is equals or greather than array length", "index");
+
IEnumerator<T> e = InternalGetEnumerator ();
int i = index;
while (e.MoveNext ()) {
- dest[i++] = e.Current;
+ if (i == array.Length - index)
+ throw new ArgumentException ("The number of elememts in the collection exceeds the capacity of array", "array");
+ array[i++] = e.Current;
}
}
bool ICollection.IsSynchronized {
- get { return true; }
+ get { return false; }
}
bool IProducerConsumerCollection<T>.TryTake (out T item)
return TryPop (out item);
}
- object syncRoot = new object ();
object ICollection.SyncRoot {
- get { return syncRoot; }
+ get {
+ throw new NotSupportedException ();
+ }
}
public T[] ToArray ()
{
- T[] dest = new T [count];
- CopyTo (dest, 0);
- return dest;
+ return new List<T> (this).ToArray ();
}
public int Count {
return count == 0;
}
}
+
+ static void RangeArgumentsCheck (T[] items, int startIndex, int count)
+ {
+ if (items == null)
+ throw new ArgumentNullException ("items");
+ if (startIndex < 0 || startIndex >= items.Length)
+ throw new ArgumentOutOfRangeException ("startIndex");
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count");
+ if (startIndex + count > items.Length)
+ throw new ArgumentException ("startIndex + count is greater than the length of items.");
+ }
}
}
#endif