Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / corlib / System.Collections.Concurrent / ConcurrentDictionary.cs
index cbd79fb00bc16ee535f98b797552e0ed3e0e67f7..2bfb952af7d33c0aaeb4fe7c33e2246e4b819528 100644 (file)
@@ -1,4 +1,4 @@
-// ConcurrentSkipList.cs
+// ConcurrentDictionary.cs
 //
 // Copyright (c) 2009 Jérémie "Garuma" Laval
 //
 //
 //
 
+#if NET_4_0 || MOBILE
+
 using System;
 using System.Threading;
 using System.Collections;
 using System.Collections.Generic;
 using System.Runtime.Serialization;
-
-#if NET_4_0 || BOOTSTRAP_NET_4_0
+using System.Diagnostics;
 
 namespace System.Collections.Concurrent
 {
+       [DebuggerDisplay ("Count={Count}")]
+       [DebuggerTypeProxy (typeof (CollectionDebuggerView<,>))]
        public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>,
          ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>,
          IDictionary, ICollection, IEnumerable
        {
                IEqualityComparer<TKey> comparer;
 
-               SplitOrderedList<KeyValuePair<TKey, TValue>> internalDictionary = new SplitOrderedList<KeyValuePair<TKey, TValue>> ();
+               SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> internalDictionary;
 
                public ConcurrentDictionary () : this (EqualityComparer<TKey>.Default)
                {
                }
 
-               public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> values)
-                       : this (values, EqualityComparer<TKey>.Default)
+               public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> collection)
+                       : this (collection, EqualityComparer<TKey>.Default)
                {
-                       foreach (KeyValuePair<TKey, TValue> pair in values)
-                               Add (pair.Key, pair.Value);
                }
 
                public ConcurrentDictionary (IEqualityComparer<TKey> comparer)
                {
                        this.comparer = comparer;
+                       this.internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> (comparer);
                }
 
-               public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> values, IEqualityComparer<TKey> comparer)
+               public ConcurrentDictionary (IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
                        : this (comparer)
                {
-                       foreach (KeyValuePair<TKey, TValue> pair in values)
+                       foreach (KeyValuePair<TKey, TValue> pair in collection)
                                Add (pair.Key, pair.Value);
                }
 
@@ -71,9 +73,9 @@ namespace System.Collections.Concurrent
                }
 
                public ConcurrentDictionary (int concurrencyLevel,
-                                            IEnumerable<KeyValuePair<TKey, TValue>> values,
+                                            IEnumerable<KeyValuePair<TKey, TValue>> collection,
                                             IEqualityComparer<TKey> comparer)
-                       : this (values, comparer)
+                       : this (collection, comparer)
                {
 
                }
@@ -85,6 +87,12 @@ namespace System.Collections.Concurrent
 
                }
 
+               void CheckKey (TKey key)
+               {
+                       if (key == null)
+                               throw new ArgumentNullException ("key");
+               }
+
                void Add (TKey key, TValue value)
                {
                        while (!TryAdd (key, value));
@@ -97,7 +105,8 @@ namespace System.Collections.Concurrent
 
                public bool TryAdd (TKey key, TValue value)
                {
-                       return internalDictionary.Insert (Hash (key), Make (key, value));
+                       CheckKey (key);
+                       return internalDictionary.Insert (Hash (key), key, Make (key, value));
                }
 
                void ICollection<KeyValuePair<TKey,TValue>>.Add (KeyValuePair<TKey, TValue> pair)
@@ -107,7 +116,13 @@ namespace System.Collections.Concurrent
 
                public TValue AddOrUpdate (TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
                {
+                       CheckKey (key);
+                       if (addValueFactory == null)
+                               throw new ArgumentNullException ("addValueFactory");
+                       if (updateValueFactory == null)
+                               throw new ArgumentNullException ("updateValueFactory");
                        return internalDictionary.InsertOrUpdate (Hash (key),
+                                                                 key,
                                                                  () => Make (key, addValueFactory (key)),
                                                                  (e) => Make (key, updateValueFactory (key, e.Value))).Value;
                }
@@ -117,27 +132,37 @@ namespace System.Collections.Concurrent
                        return AddOrUpdate (key, (_) => addValue, updateValueFactory);
                }
 
+               TValue AddOrUpdate (TKey key, TValue addValue, TValue updateValue)
+               {
+                       CheckKey (key);
+                       return internalDictionary.InsertOrUpdate (Hash (key),
+                                                                 key,
+                                                                 Make (key, addValue),
+                                                                 Make (key, updateValue)).Value;
+               }
+
                TValue GetValue (TKey key)
                {
                        TValue temp;
                        if (!TryGetValue (key, out temp))
-                               // TODO: find a correct Exception
-                               throw new ArgumentException ("Not a valid key for this dictionary", "key");
+                               throw new KeyNotFoundException (key.ToString ());
                        return temp;
                }
 
                public bool TryGetValue (TKey key, out TValue value)
                {
+                       CheckKey (key);
                        KeyValuePair<TKey, TValue> pair;
-                       bool result = internalDictionary.Find (Hash (key), out pair);
+                       bool result = internalDictionary.Find (Hash (key), key, out pair);
                        value = pair.Value;
 
                        return result;
                }
 
-               public bool TryUpdate (TKey key, TValue newValue, TValue comparand)
+               public bool TryUpdate (TKey key, TValue newValue, TValue comparisonValue)
                {
-                       return internalDictionary.CompareExchange (Hash (key), Make (key, newValue), (e) => e.Value.Equals (comparand));
+                       CheckKey (key);
+                       return internalDictionary.CompareExchange (Hash (key), key, Make (key, newValue), (e) => e.Value.Equals (comparisonValue));
                }
 
                public TValue this[TKey key] {
@@ -145,24 +170,27 @@ namespace System.Collections.Concurrent
                                return GetValue (key);
                        }
                        set {
-                               AddOrUpdate (key, (_) => value, (_, __) => value);
+                               AddOrUpdate (key, value, value);
                        }
                }
 
                public TValue GetOrAdd (TKey key, Func<TKey, TValue> valueFactory)
                {
-                       return internalDictionary.InsertOrGet (Hash (key), Make (key, valueFactory (key))).Value;
+                       CheckKey (key);
+                       return internalDictionary.InsertOrGet (Hash (key), key, Make (key, default(TValue)), () => Make (key, valueFactory (key))).Value;
                }
 
                public TValue GetOrAdd (TKey key, TValue value)
                {
-                       return GetOrAdd (key, (_) => value);
+                       CheckKey (key);
+                       return internalDictionary.InsertOrGet (Hash (key), key, Make (key, value), null).Value;
                }
 
                public bool TryRemove (TKey key, out TValue value)
                {
+                       CheckKey (key);
                        KeyValuePair<TKey, TValue> data;
-                       bool result = internalDictionary.Delete (Hash (key), out data);
+                       bool result = internalDictionary.Delete (Hash (key), key, out data);
                        value = data.Value;
                        return result;
                }
@@ -186,8 +214,9 @@ namespace System.Collections.Concurrent
 
                public bool ContainsKey (TKey key)
                {
+                       CheckKey (key);
                        KeyValuePair<TKey, TValue> dummy;
-                       return internalDictionary.Find (Hash (key), out dummy);
+                       return internalDictionary.Find (Hash (key), key, out dummy);
                }
 
                bool IDictionary.Contains (object key)
@@ -246,7 +275,7 @@ namespace System.Collections.Concurrent
                public void Clear()
                {
                        // Pronk
-                       internalDictionary = new SplitOrderedList<KeyValuePair<TKey, TValue>> ();
+                       internalDictionary = new SplitOrderedList<TKey, KeyValuePair<TKey, TValue>> (comparer);
                }
 
                public int Count {