Merge branch 'BigIntegerParse'
[mono.git] / mcs / class / corlib / System.Collections.Concurrent / ConcurrentStack.cs
index edc3c5c1f6a77fd741574d4e34147ea960f2a831..49d875e524fff02acfc01074e478054b7ad9c217 100644 (file)
@@ -1,6 +1,10 @@
 // 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
@@ -33,17 +37,18 @@ using System.Runtime.Serialization;
 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;
                
@@ -51,9 +56,12 @@ namespace System.Collections.Concurrent
                {
                }
                
-               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);
                }
                
@@ -63,10 +71,10 @@ namespace System.Collections.Concurrent
                        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);
@@ -74,19 +82,24 @@ namespace System.Collections.Concurrent
                        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;
                                
@@ -98,43 +111,48 @@ namespace System.Collections.Concurrent
                                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;
@@ -142,22 +160,24 @@ namespace System.Collections.Concurrent
                        } 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;
                }
                
@@ -192,23 +212,30 @@ namespace System.Collections.Concurrent
                
                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)
@@ -216,16 +243,15 @@ namespace System.Collections.Concurrent
                        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 {
@@ -239,6 +265,18 @@ namespace System.Collections.Concurrent
                                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