Remove ConcurrentDictionary from CoreLib (dotnet/coreclr#18308)
authorStephen Toub <stoub@microsoft.com>
Sat, 9 Jun 2018 02:41:27 +0000 (22:41 -0400)
committerGitHub <noreply@github.com>
Sat, 9 Jun 2018 02:41:27 +0000 (22:41 -0400)
Commit migrated from https://github.com/dotnet/coreclr/commit/b4617616dfc57d993f49e015cae45240f82f163b

src/coreclr/src/System.Private.CoreLib/Resources/Strings.resx
src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/coreclr/src/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentDictionary.cs [deleted file]
src/coreclr/src/System.Private.CoreLib/src/System/ThrowHelper.cs

index a21c2bc..b21ebe9 100644 (file)
   <data name="ConcurrentCollection_SyncRoot_NotSupported" xml:space="preserve">
     <value>The SyncRoot property may not be used for the synchronization of concurrent collections.</value>
   </data>
-  <data name="ConcurrentDictionary_ArrayIncorrectType" xml:space="preserve">
-    <value>The array is multidimensional, or the type parameter for the set cannot be cast automatically to the type of the destination array.</value>
-  </data>
-  <data name="ConcurrentDictionary_ArrayNotLargeEnough" xml:space="preserve">
-    <value>The index is equal to or greater than the length of the array, or the number of elements in the dictionary is greater than the available space from index to the end of the destination array.</value>
-  </data>
-  <data name="ConcurrentDictionary_CapacityMustNotBeNegative" xml:space="preserve">
-    <value>The capacity argument must be greater than or equal to zero.</value>
-  </data>
-  <data name="ConcurrentDictionary_ConcurrencyLevelMustBePositive" xml:space="preserve">
-    <value>The concurrencyLevel argument must be positive.</value>
-  </data>
-  <data name="ConcurrentDictionary_IndexIsNegative" xml:space="preserve">
-    <value>The index argument is less than zero.</value>
-  </data>
-  <data name="ConcurrentDictionary_ItemKeyIsNull" xml:space="preserve">
-    <value>TKey is a reference type and item.Key is null.</value>
-  </data>
-  <data name="ConcurrentDictionary_KeyAlreadyExisted" xml:space="preserve">
-    <value>The key already existed in the dictionary.</value>
-  </data>
-  <data name="ConcurrentDictionary_TypeOfKeyIncorrect" xml:space="preserve">
-    <value>The key was of an incorrect type for this dictionary.</value>
-  </data>
-  <data name="ConcurrentDictionary_TypeOfValueIncorrect" xml:space="preserve">
-    <value>The value was of an incorrect type for this dictionary.</value>
-  </data>
   <data name="event_Barrier_PhaseFinished" xml:space="preserve">
     <value>Barrier finishing phase {1}.</value>
   </data>
   <data name="event_ConcurrentBag_TryTakeSteals" xml:space="preserve">
     <value>ConcurrentBag stealing in TryTake.</value>
   </data>
-  <data name="event_ConcurrentDictionary_AcquiringAllLocks" xml:space="preserve">
-    <value>ConcurrentDictionary acquiring all locks on {0} bucket(s).</value>
-  </data>
   <data name="event_ConcurrentStack_FastPopFailed" xml:space="preserve">
     <value>Pop from ConcurrentStack spun {0} time(s).</value>
   </data>
   <data name="ConcurrentStack_PushPopRange_StartOutOfRange" xml:space="preserve">
     <value>The startIndex argument must be greater than or equal to zero.</value>
   </data>
-  <data name="ConcurrentDictionary_SourceContainsDuplicateKeys" xml:space="preserve">
-    <value>The source argument contains duplicate keys.</value>
-  </data>
   <data name="NotSupported_SignatureType" xml:space="preserve">
     <value>This method is not supported on signature types.</value>
   </data>
index 05b529e..b2387ce 100644 (file)
     <Compile Include="$(BclSourcesRoot)\System\Collections\Generic\ArraySortHelper.CoreCLR.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Collections\ObjectModel\ReadOnlyDictionary.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Collections\Concurrent\ConcurrentStack.cs" />
-    <Compile Include="$(BclSourcesRoot)\System\Collections\Concurrent\ConcurrentDictionary.cs" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeWaitHandle.cs" />
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentDictionary.cs
deleted file mode 100644 (file)
index cc6033f..0000000
+++ /dev/null
@@ -1,1590 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*============================================================
-**
-** Class:   ConcurrentDictionary
-**
-**
-** Purpose: A scalable dictionary for concurrent access
-**
-**
-===========================================================*/
-
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Threading;
-
-namespace System.Collections.Concurrent
-{
-    /// <summary>
-    /// Represents a thread-safe collection of keys and values.
-    /// </summary>
-    /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
-    /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
-    /// <remarks>
-    /// All public and protected members of <see cref="ConcurrentDictionary{TKey,TValue}"/> are thread-safe and may be used
-    /// concurrently from multiple threads.
-    /// </remarks>
-    [DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))]
-    [DebuggerDisplay("Count = {Count}")]
-    internal class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>
-    {
-        /// <summary>
-        /// Tables that hold the internal state of the ConcurrentDictionary
-        ///
-        /// Wrapping the three tables in a single object allows us to atomically
-        /// replace all tables at once.
-        /// </summary>
-        private sealed class Tables
-        {
-            internal readonly Node[] _buckets; // A singly-linked list for each bucket.
-            internal readonly object[] _locks; // A set of locks, each guarding a section of the table.
-            internal volatile int[] _countPerLock; // The number of elements guarded by each lock.
-
-            internal Tables(Node[] buckets, object[] locks, int[] countPerLock)
-            {
-                _buckets = buckets;
-                _locks = locks;
-                _countPerLock = countPerLock;
-            }
-        }
-
-        private volatile Tables _tables; // Internal tables of the dictionary
-        private IEqualityComparer<TKey> _comparer; // Key equality comparer
-        private readonly bool _growLockArray; // Whether to dynamically increase the size of the striped lock
-        private int _budget; // The maximum number of elements per lock before a resize operation is triggered
-
-        // The default capacity, i.e. the initial # of buckets. When choosing this value, we are making
-        // a trade-off between the size of a very small dictionary, and the number of resizes when
-        // constructing a large dictionary. Also, the capacity should not be divisible by a small prime.
-        private const int DefaultCapacity = 31;
-
-        // The maximum size of the striped lock that will not be exceeded when locks are automatically
-        // added as the dictionary grows. However, the user is allowed to exceed this limit by passing
-        // a concurrency level larger than MaxLockNumber into the constructor.
-        private const int MaxLockNumber = 1024;
-
-        // Whether TValue is a type that can be written atomically (i.e., with no danger of torn reads)
-        private static readonly bool s_isValueWriteAtomic = IsValueWriteAtomic();
-
-        /// <summary>
-        /// Determines whether type TValue can be written atomically
-        /// </summary>
-        private static bool IsValueWriteAtomic()
-        {
-            //
-            // Section 12.6.6 of ECMA CLI explains which types can be read and written atomically without
-            // the risk of tearing.
-            //
-            // See http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf
-            //
-            Type valueType = typeof(TValue);
-            if (!valueType.IsValueType)
-            {
-                return true;
-            }
-            if (valueType.IsEnum)
-            {
-                valueType = Enum.GetUnderlyingType(valueType);
-            }
-
-            switch (Type.GetTypeCode(valueType))
-            {
-                case TypeCode.Boolean:
-                case TypeCode.Byte:
-                case TypeCode.Char:
-                case TypeCode.Int16:
-                case TypeCode.Int32:
-                case TypeCode.SByte:
-                case TypeCode.Single:
-                case TypeCode.UInt16:
-                case TypeCode.UInt32:
-                    return true;
-                case TypeCode.Int64:
-                case TypeCode.Double:
-                case TypeCode.UInt64:
-                    return IntPtr.Size == 8;
-                default:
-                    return false;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>
-        /// class that is empty, has the default concurrency level, has the default initial capacity, and
-        /// uses the default comparer for the key type.
-        /// </summary>
-        public ConcurrentDictionary() : this(DefaultConcurrencyLevel, DefaultCapacity, true, null) { }
-
-        internal ConcurrentDictionary(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer<TKey> comparer)
-        {
-            if (concurrencyLevel < 1)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.concurrencyLevel, ExceptionResource.ConcurrentDictionary_ConcurrencyLevelMustBePositive);
-            }
-            if (capacity < 0)
-            {
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ConcurrentDictionary_CapacityMustNotBeNegative);
-            }
-
-            // The capacity should be at least as large as the concurrency level. Otherwise, we would have locks that don't guard
-            // any buckets.
-            if (capacity < concurrencyLevel)
-            {
-                capacity = concurrencyLevel;
-            }
-
-            object[] locks = new object[concurrencyLevel];
-            for (int i = 0; i < locks.Length; i++)
-            {
-                locks[i] = new object();
-            }
-
-            int[] countPerLock = new int[locks.Length];
-            Node[] buckets = new Node[capacity];
-            _tables = new Tables(buckets, locks, countPerLock);
-
-            _comparer = comparer ?? EqualityComparer<TKey>.Default;
-            _growLockArray = growLockArray;
-            _budget = buckets.Length / locks.Length;
-        }
-
-        /// <summary>
-        /// Attempts to add the specified key and value to the <see cref="ConcurrentDictionary{TKey,
-        /// TValue}"/>.
-        /// </summary>
-        /// <param name="key">The key of the element to add.</param>
-        /// <param name="value">The value of the element to add. The value can be a null reference (Nothing
-        /// in Visual Basic) for reference types.</param>
-        /// <returns>true if the key/value pair was added to the <see cref="ConcurrentDictionary{TKey,
-        /// TValue}"/>
-        /// successfully; otherwise, false.</returns>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null reference
-        /// (Nothing in Visual Basic).</exception>
-        /// <exception cref="T:System.OverflowException">The <see cref="ConcurrentDictionary{TKey, TValue}"/>
-        /// contains too many elements.</exception>
-        public bool TryAdd(TKey key, TValue value)
-        {
-            if (key == null) ThrowKeyNullException();
-            TValue dummy;
-            return TryAddInternal(key, _comparer.GetHashCode(key), value, false, true, out dummy);
-        }
-
-        /// <summary>
-        /// Determines whether the <see cref="ConcurrentDictionary{TKey, TValue}"/> contains the specified
-        /// key.
-        /// </summary>
-        /// <param name="key">The key to locate in the <see cref="ConcurrentDictionary{TKey,
-        /// TValue}"/>.</param>
-        /// <returns>true if the <see cref="ConcurrentDictionary{TKey, TValue}"/> contains an element with
-        /// the specified key; otherwise, false.</returns>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        public bool ContainsKey(TKey key)
-        {
-            if (key == null) ThrowKeyNullException();
-
-            TValue throwAwayValue;
-            return TryGetValue(key, out throwAwayValue);
-        }
-
-        /// <summary>
-        /// Attempts to remove and return the value with the specified key from the
-        /// <see cref="ConcurrentDictionary{TKey, TValue}"/>.
-        /// </summary>
-        /// <param name="key">The key of the element to remove and return.</param>
-        /// <param name="value">When this method returns, <paramref name="value"/> contains the object removed from the
-        /// <see cref="ConcurrentDictionary{TKey,TValue}"/> or the default value of <typeparamref
-        /// name="TValue"/>
-        /// if the operation failed.</param>
-        /// <returns>true if an object was removed successfully; otherwise, false.</returns>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        public bool TryRemove(TKey key, out TValue value)
-        {
-            if (key == null) ThrowKeyNullException();
-
-            return TryRemoveInternal(key, out value, false, default);
-        }
-
-        /// <summary>
-        /// Removes the specified key from the dictionary if it exists and returns its associated value.
-        /// If matchValue flag is set, the key will be removed only if is associated with a particular
-        /// value.
-        /// </summary>
-        /// <param name="key">The key to search for and remove if it exists.</param>
-        /// <param name="value">The variable into which the removed value, if found, is stored.</param>
-        /// <param name="matchValue">Whether removal of the key is conditional on its value.</param>
-        /// <param name="oldValue">The conditional value to compare against if <paramref name="matchValue"/> is true</param>
-        /// <returns></returns>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
-        private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue)
-        {
-            int hashcode = _comparer.GetHashCode(key);
-            while (true)
-            {
-                Tables tables = _tables;
-
-                int bucketNo, lockNo;
-                GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, tables._buckets.Length, tables._locks.Length);
-
-                lock (tables._locks[lockNo])
-                {
-                    // If the table just got resized, we may not be holding the right lock, and must retry.
-                    // This should be a rare occurrence.
-                    if (tables != _tables)
-                    {
-                        continue;
-                    }
-
-                    Node prev = null;
-                    for (Node curr = tables._buckets[bucketNo]; curr != null; curr = curr._next)
-                    {
-                        Debug.Assert((prev == null && curr == tables._buckets[bucketNo]) || prev._next == curr);
-
-                        if (hashcode == curr._hashcode && _comparer.Equals(curr._key, key))
-                        {
-                            if (matchValue)
-                            {
-                                bool valuesMatch = EqualityComparer<TValue>.Default.Equals(oldValue, curr._value);
-                                if (!valuesMatch)
-                                {
-                                    value = default;
-                                    return false;
-                                }
-                            }
-
-                            if (prev == null)
-                            {
-                                Volatile.Write<Node>(ref tables._buckets[bucketNo], curr._next);
-                            }
-                            else
-                            {
-                                prev._next = curr._next;
-                            }
-
-                            value = curr._value;
-                            tables._countPerLock[lockNo]--;
-                            return true;
-                        }
-                        prev = curr;
-                    }
-                }
-
-                value = default;
-                return false;
-            }
-        }
-
-        /// <summary>
-        /// Attempts to get the value associated with the specified key from the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">The key of the value to get.</param>
-        /// <param name="value">When this method returns, <paramref name="value"/> contains the object from
-        /// the
-        /// <see cref="ConcurrentDictionary{TKey,TValue}"/> with the specified key or the default value of
-        /// <typeparamref name="TValue"/>, if the operation failed.</param>
-        /// <returns>true if the key was found in the <see cref="ConcurrentDictionary{TKey,TValue}"/>;
-        /// otherwise, false.</returns>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
-        public bool TryGetValue(TKey key, out TValue value)
-        {
-            if (key == null) ThrowKeyNullException();
-            return TryGetValueInternal(key, _comparer.GetHashCode(key), out value);
-        }
-
-        private bool TryGetValueInternal(TKey key, int hashcode, out TValue value)
-        {
-            Debug.Assert(_comparer.GetHashCode(key) == hashcode);
-            
-            // We must capture the _buckets field in a local variable. It is set to a new table on each table resize.
-            Tables tables = _tables;
-
-            int bucketNo = GetBucket(hashcode, tables._buckets.Length);
-
-            // We can get away w/out a lock here.
-            // The Volatile.Read ensures that we have a copy of the reference to tables._buckets[bucketNo].
-            // This protects us from reading fields ('_hashcode', '_key', '_value' and '_next') of different instances.
-            Node n = Volatile.Read<Node>(ref tables._buckets[bucketNo]);
-
-            while (n != null)
-            {
-                if (hashcode == n._hashcode && _comparer.Equals(n._key, key))
-                {
-                    value = n._value;
-                    return true;
-                }
-                n = n._next;
-            }
-
-            value = default;
-            return false;
-        }
-
-        /// <summary>
-        /// Removes all keys and values from the <see cref="ConcurrentDictionary{TKey,TValue}"/>.
-        /// </summary>
-        public void Clear()
-        {
-            int locksAcquired = 0;
-            try
-            {
-                AcquireAllLocks(ref locksAcquired);
-
-                Tables newTables = new Tables(new Node[DefaultCapacity], _tables._locks, new int[_tables._countPerLock.Length]);
-                _tables = newTables;
-                _budget = Math.Max(1, newTables._buckets.Length / newTables._locks.Length);
-            }
-            finally
-            {
-                ReleaseLocks(0, locksAcquired);
-            }
-        }
-
-        /// <summary>
-        /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection"/> to an array of
-        /// type <see cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>, starting at the
-        /// specified array index.
-        /// </summary>
-        /// <param name="array">The one-dimensional array of type <see
-        /// cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
-        /// that is the destination of the <see
-        /// cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/> elements copied from the <see
-        /// cref="T:System.Collections.ICollection"/>. The array must have zero-based indexing.</param>
-        /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
-        /// begins.</param>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="array"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than
-        /// 0.</exception>
-        /// <exception cref="T:System.ArgumentException"><paramref name="index"/> is equal to or greater than
-        /// the length of the <paramref name="array"/>. -or- The number of elements in the source <see
-        /// cref="T:System.Collections.ICollection"/>
-        /// is greater than the available space from <paramref name="index"/> to the end of the destination
-        /// <paramref name="array"/>.</exception>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
-        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
-        {
-            if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            if (index < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ConcurrentDictionary_IndexIsNegative);
-
-            int locksAcquired = 0;
-            try
-            {
-                AcquireAllLocks(ref locksAcquired);
-
-                int count = 0;
-
-                for (int i = 0; i < _tables._locks.Length && count >= 0; i++)
-                {
-                    count += _tables._countPerLock[i];
-                }
-
-                if (array.Length - count < index || count < 0) //"count" itself or "count + index" can overflow
-                {
-                    ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_ArrayNotLargeEnough);
-                }
-
-                CopyToPairs(array, index);
-            }
-            finally
-            {
-                ReleaseLocks(0, locksAcquired);
-            }
-        }
-
-        /// <summary>
-        /// Copies the key and value pairs stored in the <see cref="ConcurrentDictionary{TKey,TValue}"/> to a
-        /// new array.
-        /// </summary>
-        /// <returns>A new array containing a snapshot of key and value pairs copied from the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.</returns>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
-        public KeyValuePair<TKey, TValue>[] ToArray()
-        {
-            int locksAcquired = 0;
-            try
-            {
-                AcquireAllLocks(ref locksAcquired);
-                int count = 0;
-                checked
-                {
-                    for (int i = 0; i < _tables._locks.Length; i++)
-                    {
-                        count += _tables._countPerLock[i];
-                    }
-                }
-
-                if (count == 0)
-                {
-                    return Array.Empty<KeyValuePair<TKey, TValue>>();
-                }
-
-                KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[count];
-                CopyToPairs(array, 0);
-                return array;
-            }
-            finally
-            {
-                ReleaseLocks(0, locksAcquired);
-            }
-        }
-
-        /// <summary>
-        /// Copy dictionary contents to an array - shared implementation between ToArray and CopyTo.
-        /// 
-        /// Important: the caller must hold all locks in _locks before calling CopyToPairs.
-        /// </summary>
-        private void CopyToPairs(KeyValuePair<TKey, TValue>[] array, int index)
-        {
-            Node[] buckets = _tables._buckets;
-            for (int i = 0; i < buckets.Length; i++)
-            {
-                for (Node current = buckets[i]; current != null; current = current._next)
-                {
-                    array[index] = new KeyValuePair<TKey, TValue>(current._key, current._value);
-                    index++; //this should never flow, CopyToPairs is only called when there's no overflow risk
-                }
-            }
-        }
-
-        /// <summary>
-        /// Copy dictionary contents to an array - shared implementation between ToArray and CopyTo.
-        /// 
-        /// Important: the caller must hold all locks in _locks before calling CopyToEntries.
-        /// </summary>
-        private void CopyToEntries(DictionaryEntry[] array, int index)
-        {
-            Node[] buckets = _tables._buckets;
-            for (int i = 0; i < buckets.Length; i++)
-            {
-                for (Node current = buckets[i]; current != null; current = current._next)
-                {
-                    array[index] = new DictionaryEntry(current._key, current._value);
-                    index++;  //this should never flow, CopyToEntries is only called when there's no overflow risk
-                }
-            }
-        }
-
-        /// <summary>
-        /// Copy dictionary contents to an array - shared implementation between ToArray and CopyTo.
-        /// 
-        /// Important: the caller must hold all locks in _locks before calling CopyToObjects.
-        /// </summary>
-        private void CopyToObjects(object[] array, int index)
-        {
-            Node[] buckets = _tables._buckets;
-            for (int i = 0; i < buckets.Length; i++)
-            {
-                for (Node current = buckets[i]; current != null; current = current._next)
-                {
-                    array[index] = new KeyValuePair<TKey, TValue>(current._key, current._value);
-                    index++; //this should never flow, CopyToObjects is only called when there's no overflow risk
-                }
-            }
-        }
-
-        /// <summary>Returns an enumerator that iterates through the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.</summary>
-        /// <returns>An enumerator for the <see cref="ConcurrentDictionary{TKey,TValue}"/>.</returns>
-        /// <remarks>
-        /// The enumerator returned from the dictionary is safe to use concurrently with
-        /// reads and writes to the dictionary, however it does not represent a moment-in-time snapshot
-        /// of the dictionary.  The contents exposed through the enumerator may contain modifications
-        /// made to the dictionary after <see cref="GetEnumerator"/> was called.
-        /// </remarks>
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-        {
-            Node[] buckets = _tables._buckets;
-
-            for (int i = 0; i < buckets.Length; i++)
-            {
-                // The Volatile.Read ensures that we have a copy of the reference to buckets[i].
-                // This protects us from reading fields ('_key', '_value' and '_next') of different instances.
-                Node current = Volatile.Read<Node>(ref buckets[i]);
-
-                while (current != null)
-                {
-                    yield return new KeyValuePair<TKey, TValue>(current._key, current._value);
-                    current = current._next;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Shared internal implementation for inserts and updates.
-        /// If key exists, we always return false; and if updateIfExists == true we force update with value;
-        /// If key doesn't exist, we always add value and return true;
-        /// </summary>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
-        private bool TryAddInternal(TKey key, int hashcode, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)
-        {
-            Debug.Assert(_comparer.GetHashCode(key) == hashcode);
-
-            while (true)
-            {
-                int bucketNo, lockNo;
-
-                Tables tables = _tables;
-                GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, tables._buckets.Length, tables._locks.Length);
-
-                bool resizeDesired = false;
-                bool lockTaken = false;
-                try
-                {
-                    if (acquireLock)
-                        Monitor.Enter(tables._locks[lockNo], ref lockTaken);
-
-                    // If the table just got resized, we may not be holding the right lock, and must retry.
-                    // This should be a rare occurrence.
-                    if (tables != _tables)
-                    {
-                        continue;
-                    }
-
-                    // Try to find this key in the bucket
-                    Node prev = null;
-                    for (Node node = tables._buckets[bucketNo]; node != null; node = node._next)
-                    {
-                        Debug.Assert((prev == null && node == tables._buckets[bucketNo]) || prev._next == node);
-                        if (hashcode == node._hashcode && _comparer.Equals(node._key, key))
-                        {
-                            // The key was found in the dictionary. If updates are allowed, update the value for that key.
-                            // We need to create a new node for the update, in order to support TValue types that cannot
-                            // be written atomically, since lock-free reads may be happening concurrently.
-                            if (updateIfExists)
-                            {
-                                if (s_isValueWriteAtomic)
-                                {
-                                    node._value = value;
-                                }
-                                else
-                                {
-                                    Node newNode = new Node(node._key, value, hashcode, node._next);
-                                    if (prev == null)
-                                    {
-                                        Volatile.Write(ref tables._buckets[bucketNo], newNode);
-                                    }
-                                    else
-                                    {
-                                        prev._next = newNode;
-                                    }
-                                }
-                                resultingValue = value;
-                            }
-                            else
-                            {
-                                resultingValue = node._value;
-                            }
-                            return false;
-                        }
-                        prev = node;
-                    }
-
-                    // The key was not found in the bucket. Insert the key-value pair.
-                    Volatile.Write<Node>(ref tables._buckets[bucketNo], new Node(key, value, hashcode, tables._buckets[bucketNo]));
-                    checked
-                    {
-                        tables._countPerLock[lockNo]++;
-                    }
-
-                    //
-                    // If the number of elements guarded by this lock has exceeded the budget, resize the bucket table.
-                    // It is also possible that GrowTable will increase the budget but won't resize the bucket table.
-                    // That happens if the bucket table is found to be poorly utilized due to a bad hash function.
-                    //
-                    if (tables._countPerLock[lockNo] > _budget)
-                    {
-                        resizeDesired = true;
-                    }
-                }
-                finally
-                {
-                    if (lockTaken)
-                        Monitor.Exit(tables._locks[lockNo]);
-                }
-
-                //
-                // The fact that we got here means that we just performed an insertion. If necessary, we will grow the table.
-                //
-                // Concurrency notes:
-                // - Notice that we are not holding any locks at when calling GrowTable. This is necessary to prevent deadlocks.
-                // - As a result, it is possible that GrowTable will be called unnecessarily. But, GrowTable will obtain lock 0
-                //   and then verify that the table we passed to it as the argument is still the current table.
-                //
-                if (resizeDesired)
-                {
-                    GrowTable(tables);
-                }
-
-                resultingValue = value;
-                return true;
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets the value associated with the specified key.
-        /// </summary>
-        /// <param name="key">The key of the value to get or set.</param>
-        /// <value>The value associated with the specified key. If the specified key is not found, a get
-        /// operation throws a
-        /// <see cref="T:System.Collections.Generic.KeyNotFoundException"/>, and a set operation creates a new
-        /// element with the specified key.</value>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">The property is retrieved and
-        /// <paramref name="key"/>
-        /// does not exist in the collection.</exception>
-        public TValue this[TKey key]
-        {
-            get
-            {
-                TValue value;
-                if (!TryGetValue(key, out value))
-                {
-                    ThrowKeyNotFoundException(key);
-                }
-                return value;
-            }
-            set
-            {
-                if (key == null) ThrowKeyNullException();
-                TValue dummy;
-                TryAddInternal(key, _comparer.GetHashCode(key), value, true, true, out dummy);
-            }
-        }
-
-        // These exception throwing sites have been extracted into their own methods as these are
-        // uncommonly needed and when inlined are observed to prevent the inlining of important
-        // methods like TryGetValue and ContainsKey.
-
-        private static void ThrowKeyNotFoundException(object key)
-        {
-            throw new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
-        }
-
-        private static void ThrowKeyNullException()
-        {
-            throw new ArgumentNullException("key");
-        }
-
-        /// <summary>
-        /// Gets the number of key/value pairs contained in the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <exception cref="T:System.OverflowException">The dictionary contains too many
-        /// elements.</exception>
-        /// <value>The number of key/value pairs contained in the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.</value>
-        /// <remarks>Count has snapshot semantics and represents the number of items in the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>
-        /// at the moment when Count was accessed.</remarks>
-        public int Count
-        {
-            [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
-            get
-            {
-                int acquiredLocks = 0;
-                try
-                {
-                    // Acquire all locks
-                    AcquireAllLocks(ref acquiredLocks);
-
-                    return GetCountInternal();
-                }
-                finally
-                {
-                    // Release locks that have been acquired earlier
-                    ReleaseLocks(0, acquiredLocks);
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the number of key/value pairs contained in the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>. Should only be used after all locks
-        /// have been acquired.
-        /// </summary>
-        /// <exception cref="T:System.OverflowException">The dictionary contains too many
-        /// elements.</exception>
-        /// <value>The number of key/value pairs contained in the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.</value>
-        /// <remarks>Count has snapshot semantics and represents the number of items in the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>
-        /// at the moment when Count was accessed.</remarks>
-        private int GetCountInternal()
-        {
-            int count = 0;
-
-            // Compute the count, we allow overflow
-            for (int i = 0; i < _tables._countPerLock.Length; i++)
-            {
-                count += _tables._countPerLock[i];
-            }
-
-            return count;
-        }
-
-        /// <summary>
-        /// Gets a value that indicates whether the <see cref="ConcurrentDictionary{TKey,TValue}"/> is empty.
-        /// </summary>
-        /// <value>true if the <see cref="ConcurrentDictionary{TKey,TValue}"/> is empty; otherwise,
-        /// false.</value>
-        public bool IsEmpty
-        {
-            [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
-            get
-            {
-                int acquiredLocks = 0;
-                try
-                {
-                    // Acquire all locks
-                    AcquireAllLocks(ref acquiredLocks);
-
-                    for (int i = 0; i < _tables._countPerLock.Length; i++)
-                    {
-                        if (_tables._countPerLock[i] != 0)
-                        {
-                            return false;
-                        }
-                    }
-                }
-                finally
-                {
-                    // Release locks that have been acquired earlier
-                    ReleaseLocks(0, acquiredLocks);
-                }
-
-                return true;
-            }
-        }
-
-        #region IDictionary<TKey,TValue> members
-
-        /// <summary>
-        /// Adds the specified key and value to the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">The object to use as the key of the element to add.</param>
-        /// <param name="value">The object to use as the value of the element to add.</param>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        /// <exception cref="T:System.OverflowException">The dictionary contains too many
-        /// elements.</exception>
-        /// <exception cref="T:System.ArgumentException">
-        /// An element with the same key already exists in the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.</exception>
-        void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
-        {
-            if (!TryAdd(key, value))
-            {
-                ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_KeyAlreadyExisted, ExceptionArgument.key);
-            }
-        }
-
-        /// <summary>
-        /// Removes the element with the specified key from the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">The key of the element to remove.</param>
-        /// <returns>true if the element is successfully remove; otherwise false. This method also returns
-        /// false if
-        /// <paramref name="key"/> was not found in the original <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
-        /// </returns>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        bool IDictionary<TKey, TValue>.Remove(TKey key)
-        {
-            TValue throwAwayValue;
-            return TryRemove(key, out throwAwayValue);
-        }
-
-        /// <summary>
-        /// Gets a collection containing the keys in the <see
-        /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>An <see cref="T:System.Collections.Generic.ICollection{TKey}"/> containing the keys in the
-        /// <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</value>
-        public ICollection<TKey> Keys
-        {
-            get { return GetKeys(); }
-        }
-
-        /// <summary>
-        /// Gets an <see cref="T:System.Collections.Generic.IEnumerable{TKey}"/> containing the keys of
-        /// the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>An <see cref="T:System.Collections.Generic.IEnumerable{TKey}"/> containing the keys of
-        /// the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.</value>
-        IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
-        {
-            get { return GetKeys(); }
-        }
-
-        /// <summary>
-        /// Gets a collection containing the values in the <see
-        /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>An <see cref="T:System.Collections.Generic.ICollection{TValue}"/> containing the values in
-        /// the
-        /// <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</value>
-        public ICollection<TValue> Values
-        {
-            get { return GetValues(); }
-        }
-
-        /// <summary>
-        /// Gets an <see cref="T:System.Collections.Generic.IEnumerable{TValue}"/> containing the values
-        /// in the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>An <see cref="T:System.Collections.Generic.IEnumerable{TValue}"/> containing the
-        /// values in the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.</value>
-        IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values
-        {
-            get { return GetValues(); }
-        }
-        #endregion
-
-        #region ICollection<KeyValuePair<TKey,TValue>> Members
-
-        /// <summary>
-        /// Adds the specified value to the <see cref="T:System.Collections.Generic.ICollection{TValue}"/>
-        /// with the specified key.
-        /// </summary>
-        /// <param name="keyValuePair">The <see cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
-        /// structure representing the key and value to add to the <see
-        /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</param>
-        /// <exception cref="T:System.ArgumentNullException">The <paramref name="keyValuePair"/> of <paramref
-        /// name="keyValuePair"/> is null.</exception>
-        /// <exception cref="T:System.OverflowException">The <see
-        /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>
-        /// contains too many elements.</exception>
-        /// <exception cref="T:System.ArgumentException">An element with the same key already exists in the
-        /// <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/></exception>
-        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
-        {
-            ((IDictionary<TKey, TValue>)this).Add(keyValuePair.Key, keyValuePair.Value);
-        }
-
-        /// <summary>
-        /// Determines whether the <see cref="T:System.Collections.Generic.ICollection{TKey,TValue}"/>
-        /// contains a specific key and value.
-        /// </summary>
-        /// <param name="keyValuePair">The <see cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
-        /// structure to locate in the <see
-        /// cref="T:System.Collections.Generic.ICollection{TValue}"/>.</param>
-        /// <returns>true if the <paramref name="keyValuePair"/> is found in the <see
-        /// cref="T:System.Collections.Generic.ICollection{TKey,TValue}"/>; otherwise, false.</returns>
-        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
-        {
-            TValue value;
-            if (!TryGetValue(keyValuePair.Key, out value))
-            {
-                return false;
-            }
-            return EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value);
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether the dictionary is read-only.
-        /// </summary>
-        /// <value>true if the <see cref="T:System.Collections.Generic.ICollection{TKey,TValue}"/> is
-        /// read-only; otherwise, false. For <see
-        /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>, this property always returns
-        /// false.</value>
-        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
-        {
-            get { return false; }
-        }
-
-        /// <summary>
-        /// Removes a key and value from the dictionary.
-        /// </summary>
-        /// <param name="keyValuePair">The <see
-        /// cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
-        /// structure representing the key and value to remove from the <see
-        /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</param>
-        /// <returns>true if the key and value represented by <paramref name="keyValuePair"/> is successfully
-        /// found and removed; otherwise, false.</returns>
-        /// <exception cref="T:System.ArgumentNullException">The Key property of <paramref
-        /// name="keyValuePair"/> is a null reference (Nothing in Visual Basic).</exception>
-        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair)
-        {
-            if (keyValuePair.Key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keyValuePair, ExceptionResource.ConcurrentDictionary_ItemKeyIsNull);
-
-            TValue throwAwayValue;
-            return TryRemoveInternal(keyValuePair.Key, out throwAwayValue, true, keyValuePair.Value);
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        /// <summary>Returns an enumerator that iterates through the <see
-        /// cref="ConcurrentDictionary{TKey,TValue}"/>.</summary>
-        /// <returns>An enumerator for the <see cref="ConcurrentDictionary{TKey,TValue}"/>.</returns>
-        /// <remarks>
-        /// The enumerator returned from the dictionary is safe to use concurrently with
-        /// reads and writes to the dictionary, however it does not represent a moment-in-time snapshot
-        /// of the dictionary.  The contents exposed through the enumerator may contain modifications
-        /// made to the dictionary after <see cref="GetEnumerator"/> was called.
-        /// </remarks>
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return ((ConcurrentDictionary<TKey, TValue>)this).GetEnumerator();
-        }
-
-        #endregion
-
-        #region IDictionary Members
-
-        /// <summary>
-        /// Adds the specified key and value to the dictionary.
-        /// </summary>
-        /// <param name="key">The object to use as the key.</param>
-        /// <param name="value">The object to use as the value.</param>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        /// <exception cref="T:System.OverflowException">The dictionary contains too many
-        /// elements.</exception>
-        /// <exception cref="T:System.ArgumentException">
-        /// <paramref name="key"/> is of a type that is not assignable to the key type <typeparamref
-        /// name="TKey"/> of the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>. -or-
-        /// <paramref name="value"/> is of a type that is not assignable to <typeparamref name="TValue"/>,
-        /// the type of values in the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
-        /// -or- A value with the same key already exists in the <see
-        /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
-        /// </exception>
-        void IDictionary.Add(object key, object value)
-        {
-            if (key == null) ThrowKeyNullException();
-            if (!(key is TKey)) ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfKeyIncorrect, ExceptionArgument.key);
-
-            TValue typedValue;
-            try
-            {
-                typedValue = (TValue)value;
-            }
-            catch (InvalidCastException)
-            {
-                ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfValueIncorrect, ExceptionArgument.value);
-                return;
-            }
-
-            ((IDictionary<TKey, TValue>)this).Add((TKey)key, typedValue);
-        }
-
-        /// <summary>
-        /// Gets whether the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> contains an
-        /// element with the specified key.
-        /// </summary>
-        /// <param name="key">The key to locate in the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</param>
-        /// <returns>true if the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> contains
-        /// an element with the specified key; otherwise, false.</returns>
-        /// <exception cref="T:System.ArgumentNullException"> <paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        bool IDictionary.Contains(object key)
-        {
-            if (key == null) ThrowKeyNullException();
-
-            return (key is TKey) && this.ContainsKey((TKey)key);
-        }
-
-        /// <summary>Provides an <see cref="T:System.Collections.Generics.IDictionaryEnumerator"/> for the
-        /// <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</summary>
-        /// <returns>An <see cref="T:System.Collections.Generics.IDictionaryEnumerator"/> for the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</returns>
-        IDictionaryEnumerator IDictionary.GetEnumerator()
-        {
-            return new DictionaryEnumerator(this);
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> has a fixed size.
-        /// </summary>
-        /// <value>true if the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> has a
-        /// fixed size; otherwise, false. For <see
-        /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>, this property always
-        /// returns false.</value>
-        bool IDictionary.IsFixedSize
-        {
-            get { return false; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> is read-only.
-        /// </summary>
-        /// <value>true if the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> is
-        /// read-only; otherwise, false. For <see
-        /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>, this property always
-        /// returns false.</value>
-        bool IDictionary.IsReadOnly
-        {
-            get { return false; }
-        }
-
-        /// <summary>
-        /// Gets an <see cref="T:System.Collections.ICollection"/> containing the keys of the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>An <see cref="T:System.Collections.ICollection"/> containing the keys of the <see
-        /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</value>
-        ICollection IDictionary.Keys
-        {
-            get { return GetKeys(); }
-        }
-
-        /// <summary>
-        /// Removes the element with the specified key from the <see
-        /// cref="T:System.Collections.IDictionary"/>.
-        /// </summary>
-        /// <param name="key">The key of the element to remove.</param>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        void IDictionary.Remove(object key)
-        {
-            if (key == null) ThrowKeyNullException();
-
-            TValue throwAwayValue;
-            if (key is TKey)
-            {
-                TryRemove((TKey)key, out throwAwayValue);
-            }
-        }
-
-        /// <summary>
-        /// Gets an <see cref="T:System.Collections.ICollection"/> containing the values in the <see
-        /// cref="T:System.Collections.IDictionary"/>.
-        /// </summary>
-        /// <value>An <see cref="T:System.Collections.ICollection"/> containing the values in the <see
-        /// cref="T:System.Collections.IDictionary"/>.</value>
-        ICollection IDictionary.Values
-        {
-            get { return GetValues(); }
-        }
-
-        /// <summary>
-        /// Gets or sets the value associated with the specified key.
-        /// </summary>
-        /// <param name="key">The key of the value to get or set.</param>
-        /// <value>The value associated with the specified key, or a null reference (Nothing in Visual Basic)
-        /// if <paramref name="key"/> is not in the dictionary or <paramref name="key"/> is of a type that is
-        /// not assignable to the key type <typeparamref name="TKey"/> of the <see
-        /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>.</value>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        /// <exception cref="T:System.ArgumentException">
-        /// A value is being assigned, and <paramref name="key"/> is of a type that is not assignable to the
-        /// key type <typeparamref name="TKey"/> of the <see
-        /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>. -or- A value is being
-        /// assigned, and <paramref name="key"/> is of a type that is not assignable to the value type
-        /// <typeparamref name="TValue"/> of the <see
-        /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>
-        /// </exception>
-        object IDictionary.this[object key]
-        {
-            get
-            {
-                if (key == null) ThrowKeyNullException();
-
-                TValue value;
-                if (key is TKey && TryGetValue((TKey)key, out value))
-                {
-                    return value;
-                }
-
-                return null;
-            }
-            set
-            {
-                if (key == null) ThrowKeyNullException();
-
-                if (!(key is TKey)) ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfKeyIncorrect, ExceptionArgument.key);
-                if (!(value is TValue)) ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_TypeOfValueIncorrect, ExceptionArgument.value);
-
-                ((ConcurrentDictionary<TKey, TValue>)this)[(TKey)key] = (TValue)value;
-            }
-        }
-
-        #endregion
-
-        #region ICollection Members
-
-        /// <summary>
-        /// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an array, starting
-        /// at the specified array index.
-        /// </summary>
-        /// <param name="array">The one-dimensional array that is the destination of the elements copied from
-        /// the <see cref="T:System.Collections.ICollection"/>. The array must have zero-based
-        /// indexing.</param>
-        /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
-        /// begins.</param>
-        /// <exception cref="T:System.ArgumentNullException"><paramref name="array"/> is a null reference
-        /// (Nothing in Visual Basic).</exception>
-        /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than
-        /// 0.</exception>
-        /// <exception cref="T:System.ArgumentException"><paramref name="index"/> is equal to or greater than
-        /// the length of the <paramref name="array"/>. -or- The number of elements in the source <see
-        /// cref="T:System.Collections.ICollection"/>
-        /// is greater than the available space from <paramref name="index"/> to the end of the destination
-        /// <paramref name="array"/>.</exception>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
-        void ICollection.CopyTo(Array array, int index)
-        {
-            if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            if (index < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ConcurrentDictionary_IndexIsNegative);
-
-            int locksAcquired = 0;
-            try
-            {
-                AcquireAllLocks(ref locksAcquired);
-                Tables tables = _tables;
-
-                int count = 0;
-
-                for (int i = 0; i < tables._locks.Length && count >= 0; i++)
-                {
-                    count += tables._countPerLock[i];
-                }
-
-                if (array.Length - count < index || count < 0) //"count" itself or "count + index" can overflow
-                {
-                    ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_ArrayNotLargeEnough);
-                }
-
-                // To be consistent with the behavior of ICollection.CopyTo() in Dictionary<TKey,TValue>,
-                // we recognize three types of target arrays:
-                //    - an array of KeyValuePair<TKey, TValue> structs
-                //    - an array of DictionaryEntry structs
-                //    - an array of objects
-
-                KeyValuePair<TKey, TValue>[] pairs = array as KeyValuePair<TKey, TValue>[];
-                if (pairs != null)
-                {
-                    CopyToPairs(pairs, index);
-                    return;
-                }
-
-                DictionaryEntry[] entries = array as DictionaryEntry[];
-                if (entries != null)
-                {
-                    CopyToEntries(entries, index);
-                    return;
-                }
-
-                object[] objects = array as object[];
-                if (objects != null)
-                {
-                    CopyToObjects(objects, index);
-                    return;
-                }
-
-                ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_ArrayIncorrectType, ExceptionArgument.array);
-            }
-            finally
-            {
-                ReleaseLocks(0, locksAcquired);
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is
-        /// synchronized with the SyncRoot.
-        /// </summary>
-        /// <value>true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized
-        /// (thread safe); otherwise, false. For <see
-        /// cref="T:System.Collections.Concurrent.ConcurrentDictionary{TKey,TValue}"/>, this property always
-        /// returns false.</value>
-        bool ICollection.IsSynchronized
-        {
-            get { return false; }
-        }
-
-        /// <summary>
-        /// Gets an object that can be used to synchronize access to the <see
-        /// cref="T:System.Collections.ICollection"/>. This property is not supported.
-        /// </summary>
-        /// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported.</exception>
-        object ICollection.SyncRoot
-        {
-            get
-            {
-                ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported);
-                return default;
-            }
-        }
-
-        #endregion
-
-        /// <summary>
-        /// Replaces the bucket table with a larger one. To prevent multiple threads from resizing the
-        /// table as a result of races, the Tables instance that holds the table of buckets deemed too
-        /// small is passed in as an argument to GrowTable(). GrowTable() obtains a lock, and then checks
-        /// the Tables instance has been replaced in the meantime or not.
-        /// </summary>
-        private void GrowTable(Tables tables)
-        {
-            const int MaxArrayLength = 0X7FEFFFFF;
-            int locksAcquired = 0;
-            try
-            {
-                // The thread that first obtains _locks[0] will be the one doing the resize operation
-                AcquireLocks(0, 1, ref locksAcquired);
-
-                // Make sure nobody resized the table while we were waiting for lock 0:
-                if (tables != _tables)
-                {
-                    // We assume that since the table reference is different, it was already resized (or the budget
-                    // was adjusted). If we ever decide to do table shrinking, or replace the table for other reasons,
-                    // we will have to revisit this logic.
-                    return;
-                }
-
-                // Compute the (approx.) total size. Use an Int64 accumulation variable to avoid an overflow.
-                long approxCount = 0;
-                for (int i = 0; i < tables._countPerLock.Length; i++)
-                {
-                    approxCount += tables._countPerLock[i];
-                }
-
-                //
-                // If the bucket array is too empty, double the budget instead of resizing the table
-                //
-                if (approxCount < tables._buckets.Length / 4)
-                {
-                    _budget = 2 * _budget;
-                    if (_budget < 0)
-                    {
-                        _budget = int.MaxValue;
-                    }
-                    return;
-                }
-
-
-                // Compute the new table size. We find the smallest integer larger than twice the previous table size, and not divisible by
-                // 2,3,5 or 7. We can consider a different table-sizing policy in the future.
-                int newLength = 0;
-                bool maximizeTableSize = false;
-                try
-                {
-                    checked
-                    {
-                        // Double the size of the buckets table and add one, so that we have an odd integer.
-                        newLength = tables._buckets.Length * 2 + 1;
-
-                        // Now, we only need to check odd integers, and find the first that is not divisible
-                        // by 3, 5 or 7.
-                        while (newLength % 3 == 0 || newLength % 5 == 0 || newLength % 7 == 0)
-                        {
-                            newLength += 2;
-                        }
-
-                        Debug.Assert(newLength % 2 != 0);
-
-                        if (newLength > MaxArrayLength)
-                        {
-                            maximizeTableSize = true;
-                        }
-                    }
-                }
-                catch (OverflowException)
-                {
-                    maximizeTableSize = true;
-                }
-
-                if (maximizeTableSize)
-                {
-                    newLength = MaxArrayLength;
-
-                    // We want to make sure that GrowTable will not be called again, since table is at the maximum size.
-                    // To achieve that, we set the budget to int.MaxValue.
-                    //
-                    // (There is one special case that would allow GrowTable() to be called in the future: 
-                    // calling Clear() on the ConcurrentDictionary will shrink the table and lower the budget.)
-                    _budget = int.MaxValue;
-                }
-
-                // Now acquire all other locks for the table
-                AcquireLocks(1, tables._locks.Length, ref locksAcquired);
-
-                object[] newLocks = tables._locks;
-
-                // Add more locks
-                if (_growLockArray && tables._locks.Length < MaxLockNumber)
-                {
-                    newLocks = new object[tables._locks.Length * 2];
-                    Array.Copy(tables._locks, 0, newLocks, 0, tables._locks.Length);
-                    for (int i = tables._locks.Length; i < newLocks.Length; i++)
-                    {
-                        newLocks[i] = new object();
-                    }
-                }
-
-                Node[] newBuckets = new Node[newLength];
-                int[] newCountPerLock = new int[newLocks.Length];
-
-                // Copy all data into a new table, creating new nodes for all elements
-                for (int i = 0; i < tables._buckets.Length; i++)
-                {
-                    Node current = tables._buckets[i];
-                    while (current != null)
-                    {
-                        Node next = current._next;
-                        int newBucketNo, newLockNo;
-                        GetBucketAndLockNo(current._hashcode, out newBucketNo, out newLockNo, newBuckets.Length, newLocks.Length);
-
-                        newBuckets[newBucketNo] = new Node(current._key, current._value, current._hashcode, newBuckets[newBucketNo]);
-
-                        checked
-                        {
-                            newCountPerLock[newLockNo]++;
-                        }
-
-                        current = next;
-                    }
-                }
-
-                // Adjust the budget
-                _budget = Math.Max(1, newBuckets.Length / newLocks.Length);
-
-                // Replace tables with the new versions
-                _tables = new Tables(newBuckets, newLocks, newCountPerLock);
-            }
-            finally
-            {
-                // Release all locks that we took earlier
-                ReleaseLocks(0, locksAcquired);
-            }
-        }
-
-        /// <summary>
-        /// Computes the bucket for a particular key. 
-        /// </summary>
-        private static int GetBucket(int hashcode, int bucketCount)
-        {
-            int bucketNo = (hashcode & 0x7fffffff) % bucketCount;
-            Debug.Assert(bucketNo >= 0 && bucketNo < bucketCount);
-            return bucketNo;
-        }
-
-        /// <summary>
-        /// Computes the bucket and lock number for a particular key. 
-        /// </summary>
-        private static void GetBucketAndLockNo(int hashcode, out int bucketNo, out int lockNo, int bucketCount, int lockCount)
-        {
-            bucketNo = (hashcode & 0x7fffffff) % bucketCount;
-            lockNo = bucketNo % lockCount;
-
-            Debug.Assert(bucketNo >= 0 && bucketNo < bucketCount);
-            Debug.Assert(lockNo >= 0 && lockNo < lockCount);
-        }
-
-        /// <summary>
-        /// The number of concurrent writes for which to optimize by default.
-        /// </summary>
-        private static int DefaultConcurrencyLevel
-        {
-            get { return PlatformHelper.ProcessorCount; }
-        }
-
-        /// <summary>
-        /// Acquires all locks for this hash table, and increments locksAcquired by the number
-        /// of locks that were successfully acquired. The locks are acquired in an increasing
-        /// order.
-        /// </summary>
-        private void AcquireAllLocks(ref int locksAcquired)
-        {
-            // First, acquire lock 0
-            AcquireLocks(0, 1, ref locksAcquired);
-
-            // Now that we have lock 0, the _locks array will not change (i.e., grow),
-            // and so we can safely read _locks.Length.
-            AcquireLocks(1, _tables._locks.Length, ref locksAcquired);
-            Debug.Assert(locksAcquired == _tables._locks.Length);
-        }
-
-        /// <summary>
-        /// Acquires a contiguous range of locks for this hash table, and increments locksAcquired
-        /// by the number of locks that were successfully acquired. The locks are acquired in an
-        /// increasing order.
-        /// </summary>
-        private void AcquireLocks(int fromInclusive, int toExclusive, ref int locksAcquired)
-        {
-            Debug.Assert(fromInclusive <= toExclusive);
-            object[] locks = _tables._locks;
-
-            for (int i = fromInclusive; i < toExclusive; i++)
-            {
-                bool lockTaken = false;
-                try
-                {
-                    Monitor.Enter(locks[i], ref lockTaken);
-                }
-                finally
-                {
-                    if (lockTaken)
-                    {
-                        locksAcquired++;
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Releases a contiguous range of locks.
-        /// </summary>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
-        private void ReleaseLocks(int fromInclusive, int toExclusive)
-        {
-            Debug.Assert(fromInclusive <= toExclusive);
-
-            for (int i = fromInclusive; i < toExclusive; i++)
-            {
-                Monitor.Exit(_tables._locks[i]);
-            }
-        }
-
-        /// <summary>
-        /// Gets a collection containing the keys in the dictionary.
-        /// </summary>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
-        private ReadOnlyCollection<TKey> GetKeys()
-        {
-            int locksAcquired = 0;
-            try
-            {
-                AcquireAllLocks(ref locksAcquired);
-
-                int count = GetCountInternal();
-                if (count < 0) ThrowHelper.ThrowOutOfMemoryException();
-
-                List<TKey> keys = new List<TKey>(count);
-                for (int i = 0; i < _tables._buckets.Length; i++)
-                {
-                    Node current = _tables._buckets[i];
-                    while (current != null)
-                    {
-                        keys.Add(current._key);
-                        current = current._next;
-                    }
-                }
-
-                return new ReadOnlyCollection<TKey>(keys);
-            }
-            finally
-            {
-                ReleaseLocks(0, locksAcquired);
-            }
-        }
-
-        /// <summary>
-        /// Gets a collection containing the values in the dictionary.
-        /// </summary>
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
-        private ReadOnlyCollection<TValue> GetValues()
-        {
-            int locksAcquired = 0;
-            try
-            {
-                AcquireAllLocks(ref locksAcquired);
-
-                int count = GetCountInternal();
-                if (count < 0) ThrowHelper.ThrowOutOfMemoryException();
-
-                List<TValue> values = new List<TValue>(count);
-                for (int i = 0; i < _tables._buckets.Length; i++)
-                {
-                    Node current = _tables._buckets[i];
-                    while (current != null)
-                    {
-                        values.Add(current._value);
-                        current = current._next;
-                    }
-                }
-
-                return new ReadOnlyCollection<TValue>(values);
-            }
-            finally
-            {
-                ReleaseLocks(0, locksAcquired);
-            }
-        }
-
-        /// <summary>
-        /// A node in a singly-linked list representing a particular hash table bucket.
-        /// </summary>
-        private sealed class Node
-        {
-            internal readonly TKey _key;
-            internal TValue _value;
-            internal volatile Node _next;
-            internal readonly int _hashcode;
-
-            internal Node(TKey key, TValue value, int hashcode, Node next)
-            {
-                _key = key;
-                _value = value;
-                _next = next;
-                _hashcode = hashcode;
-            }
-        }
-
-        /// <summary>
-        /// A private class to represent enumeration over the dictionary that implements the 
-        /// IDictionaryEnumerator interface.
-        /// </summary>
-        private sealed class DictionaryEnumerator : IDictionaryEnumerator
-        {
-            IEnumerator<KeyValuePair<TKey, TValue>> _enumerator; // Enumerator over the dictionary.
-
-            internal DictionaryEnumerator(ConcurrentDictionary<TKey, TValue> dictionary)
-            {
-                _enumerator = dictionary.GetEnumerator();
-            }
-
-            public DictionaryEntry Entry
-            {
-                get { return new DictionaryEntry(_enumerator.Current.Key, _enumerator.Current.Value); }
-            }
-
-            public object Key
-            {
-                get { return _enumerator.Current.Key; }
-            }
-
-            public object Value
-            {
-                get { return _enumerator.Current.Value; }
-            }
-
-            public object Current
-            {
-                get { return Entry; }
-            }
-
-            public bool MoveNext()
-            {
-                return _enumerator.MoveNext();
-            }
-
-            public void Reset()
-            {
-                _enumerator.Reset();
-            }
-        }
-    }
-}
index 7ec7a57..e7f73b5 100644 (file)
@@ -461,7 +461,6 @@ namespace System
         beginMethod,
         continuationOptions,
         continuationAction,
-        concurrencyLevel,
         text,
         callBack,
         type,
@@ -470,7 +469,6 @@ namespace System
         values,
         task,
         s,
-        keyValuePair,
         input,
         pointer,
         start,
@@ -576,15 +574,6 @@ namespace System
         MemoryDisposed,
         Memory_OutstandingReferences,
         InvalidOperation_WrongAsyncResultOrEndCalledMultiple,
-        ConcurrentDictionary_ConcurrencyLevelMustBePositive,
-        ConcurrentDictionary_CapacityMustNotBeNegative,
-        ConcurrentDictionary_TypeOfValueIncorrect,
-        ConcurrentDictionary_TypeOfKeyIncorrect,
-        ConcurrentDictionary_KeyAlreadyExisted,
-        ConcurrentDictionary_ItemKeyIsNull,
-        ConcurrentDictionary_IndexIsNegative,
-        ConcurrentDictionary_ArrayNotLargeEnough,
-        ConcurrentDictionary_ArrayIncorrectType,
         ConcurrentCollection_SyncRoot_NotSupported,
         ArgumentOutOfRange_Enum,
         InvalidOperation_HandleIsNotInitialized,