#if !UNITY_WSA 
 | 
using System; 
 | 
using System.Collections; 
 | 
using System.Collections.Generic; 
 | 
using System.Collections.ObjectModel; 
 | 
using System.Diagnostics; 
 | 
using System.Runtime.InteropServices; 
 | 
using System.Runtime.Serialization; 
 | 
using System.Threading; 
 | 
  
 | 
namespace TcpServer 
 | 
{ 
 | 
  
 | 
    /// <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>  
 | 
    [Serializable] 
 | 
    [ComVisible(false)] 
 | 
    [DebuggerDisplay("Count = {Count}")] 
 | 
    //    [HostProtection(Synchronization = true, ExternalThreading = true)] 
 | 
    public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary 
 | 
    { 
 | 
        [NonSerialized] 
 | 
        private volatile Node[] m_buckets; 
 | 
        // A singly-linked list for each bucket. 
 | 
        [NonSerialized] 
 | 
        private object[] m_locks; 
 | 
        // A set of locks, each guarding a section of the table. 
 | 
        [NonSerialized] 
 | 
        private volatile int[] m_countPerLock; 
 | 
        // The number of elements guarded by each lock. 
 | 
        private IEqualityComparer<TKey> m_comparer; 
 | 
        // Key equality comparer 
 | 
  
 | 
        private KeyValuePair<TKey, TValue>[] m_serializationArray; 
 | 
        // Used for custom serialization 
 | 
  
 | 
        private int m_serializationConcurrencyLevel; 
 | 
        // used to save the concurrency level in serialization 
 | 
  
 | 
        private int m_serializationCapacity; 
 | 
        // used to save the capacity in serialization 
 | 
  
 | 
        // The default concurrency level is DEFAULT_CONCURRENCY_MULTIPLIER * #CPUs. The higher the 
 | 
        // DEFAULT_CONCURRENCY_MULTIPLIER, the more concurrent writes can take place without interference 
 | 
        // and blocking, but also the more expensive operations that require all locks become (e.g. table 
 | 
        // resizing, ToArray, Count, etc). According to brief benchmarks that we ran, 4 seems like a good 
 | 
        // compromise. 
 | 
        private const int DEFAULT_CONCURRENCY_MULTIPLIER = 4; 
 | 
  
 | 
        // 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 DEFAULT_CAPACITY = 31; 
 | 
  
 | 
        /// <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, DEFAULT_CAPACITY) 
 | 
        { 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Initializes a new instance of the <see 
 | 
        /// cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// class that is empty, has the specified concurrency level and capacity, and uses the default  
 | 
        /// comparer for the key type. 
 | 
        /// </summary>  
 | 
        /// <param name="concurrencyLevel">The estimated number of threads that will update the  
 | 
        /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param> 
 | 
        /// <param name="capacity">The initial number of elements that the <see  
 | 
        /// cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// can contain.</param> 
 | 
        /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="concurrencyLevel"/> is 
 | 
        /// less than 1.</exception>  
 | 
        /// <exception cref="T:System.ArgumentOutOfRangeException"> <paramref name="capacity"/> is less than 
 | 
        /// 0.</exception>  
 | 
        public ConcurrentDictionary(int concurrencyLevel, int capacity) : this(concurrencyLevel, capacity, EqualityComparer<TKey>.Default) 
 | 
        { 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// class that contains elements copied from the specified <see 
 | 
        /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/>, has the default concurrency 
 | 
        /// level, has the default initial capacity, and uses the default comparer for the key type.  
 | 
        /// </summary> 
 | 
        /// <param name="collection">The <see  
 | 
        /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to  
 | 
        /// the new 
 | 
        /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param>  
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is a null reference 
 | 
        /// (Nothing in Visual Basic).</exception> 
 | 
        /// <exception cref="T:System.ArgumentException"><paramref name="collection"/> contains one or more 
 | 
        /// duplicate keys.</exception>  
 | 
        public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : this(collection, EqualityComparer<TKey>.Default) 
 | 
        { 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// class that is empty, has the specified concurrency level and capacity, and uses the specified  
 | 
        /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>. 
 | 
        /// </summary> 
 | 
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> 
 | 
        /// implementation to use when comparing keys.</param>  
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="comparer"/> is a null reference 
 | 
        /// (Nothing in Visual Basic).</exception>  
 | 
        public ConcurrentDictionary(IEqualityComparer<TKey> comparer) : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, comparer) 
 | 
        { 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// class that contains elements copied from the specified <see 
 | 
        /// cref="T:System.Collections.IEnumerable"/>, has the default concurrency level, has the default 
 | 
        /// initial capacity, and uses the specified  
 | 
        /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>. 
 | 
        /// </summary>  
 | 
        /// <param name="collection">The <see  
 | 
        /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to 
 | 
        /// the new  
 | 
        /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param> 
 | 
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> 
 | 
        /// implementation to use when comparing keys.</param> 
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is a null reference  
 | 
        /// (Nothing in Visual Basic). -or- 
 | 
        /// <paramref name="comparer"/> is a null reference (Nothing in Visual Basic).  
 | 
        /// </exception>  
 | 
        public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) 
 | 
            : this(DefaultConcurrencyLevel, collection, comparer) 
 | 
        { 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// class that contains elements copied from the specified <see cref="T:System.Collections.IEnumerable"/>,  
 | 
        /// has the specified concurrency level, has the specified initial capacity, and uses the specified 
 | 
        /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>.  
 | 
        /// </summary>  
 | 
        /// <param name="concurrencyLevel">The estimated number of threads that will update the 
 | 
        /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param>  
 | 
        /// <param name="collection">The <see cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to the new 
 | 
        /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param> 
 | 
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> implementation to use 
 | 
        /// when comparing keys.</param>  
 | 
        /// <exception cref="T:System.ArgumentNullException"> 
 | 
        /// <paramref name="collection"/> is a null reference (Nothing in Visual Basic).  
 | 
        /// -or-  
 | 
        /// <paramref name="comparer"/> is a null reference (Nothing in Visual Basic). 
 | 
        /// </exception>  
 | 
        /// <exception cref="T:System.ArgumentOutOfRangeException"> 
 | 
        /// <paramref name="concurrencyLevel"/> is less than 1. 
 | 
        /// </exception> 
 | 
        /// <exception cref="T:System.ArgumentException"><paramref name="collection"/> contains one or more duplicate keys.</exception>  
 | 
        public ConcurrentDictionary( 
 | 
            int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) 
 | 
            : this(concurrencyLevel, DEFAULT_CAPACITY, comparer) 
 | 
        { 
 | 
            if (collection == null) 
 | 
                throw new ArgumentNullException("collection"); 
 | 
            if (comparer == null) 
 | 
                throw new ArgumentNullException("comparer"); 
 | 
  
 | 
            InitializeFromCollection(collection); 
 | 
        } 
 | 
  
 | 
        private void InitializeFromCollection(IEnumerable<KeyValuePair<TKey, TValue>> collection) 
 | 
        { 
 | 
            TValue dummy; 
 | 
            foreach (KeyValuePair<TKey, TValue> pair in collection) 
 | 
            { 
 | 
                if (pair.Key == null) 
 | 
                    throw new ArgumentNullException("key"); 
 | 
  
 | 
                if (!TryAddInternal(pair.Key, pair.Value, false, false, out dummy)) 
 | 
                { 
 | 
                    throw new ArgumentException(GetResource("ConcurrentDictionary_SourceContainsDuplicateKeys")); 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// class that is empty, has the specified concurrency level, has the specified initial capacity, and  
 | 
        /// uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>. 
 | 
        /// </summary>  
 | 
        /// <param name="concurrencyLevel">The estimated number of threads that will update the  
 | 
        /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param> 
 | 
        /// <param name="capacity">The initial number of elements that the <see  
 | 
        /// cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// can contain.</param> 
 | 
        /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> 
 | 
        /// implementation to use when comparing keys.</param>  
 | 
        /// <exception cref="T:System.ArgumentOutOfRangeException"> 
 | 
        /// <paramref name="concurrencyLevel"/> is less than 1. -or-  
 | 
        /// <paramref name="capacity"/> is less than 0.  
 | 
        /// </exception> 
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="comparer"/> is a null reference  
 | 
        /// (Nothing in Visual Basic).</exception> 
 | 
        public ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer) 
 | 
        { 
 | 
            if (concurrencyLevel < 1) 
 | 
            { 
 | 
                throw new ArgumentOutOfRangeException("concurrencyLevel", GetResource("ConcurrentDictionary_ConcurrencyLevelMustBePositive")); 
 | 
            } 
 | 
            if (capacity < 0) 
 | 
            { 
 | 
                throw new ArgumentOutOfRangeException("capacity", GetResource("ConcurrentDictionary_CapacityMustNotBeNegative")); 
 | 
            } 
 | 
            if (comparer == null) 
 | 
                throw new ArgumentNullException("comparer"); 
 | 
  
 | 
            // 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; 
 | 
            } 
 | 
  
 | 
            m_locks = new object[concurrencyLevel]; 
 | 
            for (int i = 0; i < m_locks.Length; i++) 
 | 
            { 
 | 
                m_locks[i] = new object(); 
 | 
            } 
 | 
  
 | 
            m_countPerLock = new int[m_locks.Length]; 
 | 
            m_buckets = new Node[capacity]; 
 | 
            m_comparer = comparer; 
 | 
        } 
 | 
  
 | 
  
 | 
        /// <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) 
 | 
                throw new ArgumentNullException("key"); 
 | 
            TValue dummy; 
 | 
            return TryAddInternal(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) 
 | 
                throw new ArgumentNullException("key"); 
 | 
  
 | 
            TValue throwAwayValue; 
 | 
            return TryGetValue(key, out throwAwayValue); 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Attempts to remove and return the 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) 
 | 
                throw new ArgumentNullException("key"); 
 | 
  
 | 
            return TryRemoveInternal(key, out value, false, default(TValue)); 
 | 
        } 
 | 
  
 | 
        /// <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> 
 | 
        private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue) 
 | 
        { 
 | 
            while (true) 
 | 
            { 
 | 
                Node[] buckets = m_buckets; 
 | 
  
 | 
                int bucketNo, lockNo; 
 | 
                GetBucketAndLockNo(m_comparer.GetHashCode(key), out bucketNo, out lockNo, buckets.Length); 
 | 
  
 | 
                lock (m_locks[lockNo]) 
 | 
                { 
 | 
                    // If the table just got resized, we may not be holding the right lock, and must retry.  
 | 
                    // This should be a rare occurence. 
 | 
                    if (buckets != m_buckets) 
 | 
                    { 
 | 
                        continue; 
 | 
                    } 
 | 
  
 | 
                    Node prev = null; 
 | 
                    for (Node curr = m_buckets[bucketNo]; curr != null; curr = curr.m_next) 
 | 
                    { 
 | 
                        Assert((prev == null && curr == m_buckets[bucketNo]) || prev.m_next == curr); 
 | 
  
 | 
                        if (m_comparer.Equals(curr.m_key, key)) 
 | 
                        { 
 | 
                            if (matchValue) 
 | 
                            { 
 | 
                                bool valuesMatch = EqualityComparer<TValue>.Default.Equals(oldValue, curr.m_value); 
 | 
                                if (!valuesMatch) 
 | 
                                { 
 | 
                                    value = default(TValue); 
 | 
                                    return false; 
 | 
                                } 
 | 
                            } 
 | 
  
 | 
                            if (prev == null) 
 | 
                            { 
 | 
                                m_buckets[bucketNo] = curr.m_next; 
 | 
                            } 
 | 
                            else 
 | 
                            { 
 | 
                                prev.m_next = curr.m_next; 
 | 
                            } 
 | 
  
 | 
                            value = curr.m_value; 
 | 
                            m_countPerLock[lockNo]--; 
 | 
                            return true; 
 | 
                        } 
 | 
                        prev = curr; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                value = default(TValue); 
 | 
                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 spedified 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> 
 | 
        public bool TryGetValue(TKey key, out TValue value) 
 | 
        { 
 | 
            if (key == null) 
 | 
                throw new ArgumentNullException("key"); 
 | 
  
 | 
            int bucketNo, lockNoUnused; 
 | 
  
 | 
            // We must capture the m_buckets field in a local variable. It is set to a new table on each table resize.  
 | 
            Node[] buckets = m_buckets; 
 | 
            GetBucketAndLockNo(m_comparer.GetHashCode(key), out bucketNo, out lockNoUnused, buckets.Length); 
 | 
  
 | 
            // We can get away w/out a lock here. 
 | 
            Node n = buckets[bucketNo]; 
 | 
  
 | 
            // The memory barrier ensures that the load of the fields of 'n' doesn’t move before the load from buckets[i].  
 | 
            Thread.MemoryBarrier(); 
 | 
            while (n != null) 
 | 
            { 
 | 
                if (m_comparer.Equals(n.m_key, key)) 
 | 
                { 
 | 
                    value = n.m_value; 
 | 
                    return true; 
 | 
                } 
 | 
                n = n.m_next; 
 | 
            } 
 | 
  
 | 
            value = default(TValue); 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Compares the existing value for the specified key with a specified value, and if they’re equal, 
 | 
        /// updates the key with a third value.  
 | 
        /// </summary> 
 | 
        /// <param name="key">The key whose value is compared with <paramref name="comparisonValue"/> and  
 | 
        /// possibly replaced.</param>  
 | 
        /// <param name="newValue">The value that replaces the value of the element with <paramref 
 | 
        /// name="key"/> if the comparison results in equality.</param>  
 | 
        /// <param name="comparisonValue">The value that is compared to the value of the element with 
 | 
        /// <paramref name="key"/>.</param> 
 | 
        /// <returns>true if the value with <paramref name="key"/> was equal to <paramref 
 | 
        /// name="comparisonValue"/> and replaced with <paramref name="newValue"/>; otherwise,  
 | 
        /// false.</returns> 
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null  
 | 
        /// reference.</exception>  
 | 
        public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue) 
 | 
        { 
 | 
            if (key == null) 
 | 
                throw new ArgumentNullException("key"); 
 | 
  
 | 
            int hashcode = m_comparer.GetHashCode(key); 
 | 
            IEqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default; 
 | 
  
 | 
            while (true) 
 | 
            { 
 | 
                int bucketNo; 
 | 
                int lockNo; 
 | 
  
 | 
                Node[] buckets = m_buckets; 
 | 
                GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, buckets.Length); 
 | 
  
 | 
                lock (m_locks[lockNo]) 
 | 
                { 
 | 
                    // If the table just got resized, we may not be holding the right lock, and must retry.  
 | 
                    // This should be a rare occurence. 
 | 
                    if (buckets != m_buckets) 
 | 
                    { 
 | 
                        continue; 
 | 
                    } 
 | 
  
 | 
                    // Try to find this key in the bucket 
 | 
                    Node prev = null; 
 | 
                    for (Node node = buckets[bucketNo]; node != null; node = node.m_next) 
 | 
                    { 
 | 
                        Assert((prev == null && node == m_buckets[bucketNo]) || prev.m_next == node); 
 | 
                        if (m_comparer.Equals(node.m_key, key)) 
 | 
                        { 
 | 
                            if (valueComparer.Equals(node.m_value, comparisonValue)) 
 | 
                            { 
 | 
                                // Replace the old node with a new node. Unfortunately, we cannot simply 
 | 
                                // change node.m_value in place. We don't know the size of TValue, so  
 | 
                                // its writes may not be atomic.  
 | 
                                Node newNode = new Node(node.m_key, newValue, hashcode, node.m_next); 
 | 
  
 | 
                                if (prev == null) 
 | 
                                { 
 | 
                                    buckets[bucketNo] = newNode; 
 | 
                                } 
 | 
                                else 
 | 
                                { 
 | 
                                    prev.m_next = newNode; 
 | 
                                } 
 | 
  
 | 
                                return true; 
 | 
                            } 
 | 
  
 | 
                            return false; 
 | 
                        } 
 | 
  
 | 
                        prev = node; 
 | 
                    } 
 | 
  
 | 
                    //didn't find the key 
 | 
                    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); 
 | 
  
 | 
                m_buckets = new Node[DEFAULT_CAPACITY]; 
 | 
                Array.Clear(m_countPerLock, 0, m_countPerLock.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> 
 | 
        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index) 
 | 
        { 
 | 
            if (array == null) 
 | 
                throw new ArgumentNullException("array"); 
 | 
            if (index < 0) 
 | 
                throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative")); 
 | 
  
 | 
            int locksAcquired = 0; 
 | 
            try 
 | 
            { 
 | 
                AcquireAllLocks(ref locksAcquired); 
 | 
  
 | 
                int count = 0; 
 | 
  
 | 
                for (int i = 0; i < m_locks.Length; i++) 
 | 
                { 
 | 
                    count += m_countPerLock[i]; 
 | 
                } 
 | 
  
 | 
                if (array.Length - count < index || count < 0) 
 | 
                { //"count" itself or "count + index" can overflow 
 | 
                    throw new ArgumentException(GetResource("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> 
 | 
        public KeyValuePair<TKey, TValue>[] ToArray() 
 | 
        { 
 | 
            int locksAcquired = 0; 
 | 
            try 
 | 
            { 
 | 
                AcquireAllLocks(ref locksAcquired); 
 | 
                int count = 0; 
 | 
                checked 
 | 
                { 
 | 
                    for (int i = 0; i < m_locks.Length; i++) 
 | 
                    { 
 | 
                        count += m_countPerLock[i]; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                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 m_locks before calling CopyToPairs.  
 | 
        /// </summary> 
 | 
        private void CopyToPairs(KeyValuePair<TKey, TValue>[] array, int index) 
 | 
        { 
 | 
            Node[] buckets = m_buckets; 
 | 
            for (int i = 0; i < buckets.Length; i++) 
 | 
            { 
 | 
                for (Node current = buckets[i]; current != null; current = current.m_next) 
 | 
                { 
 | 
                    array[index] = new KeyValuePair<TKey, TValue>(current.m_key, current.m_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 m_locks before calling CopyToEntries.  
 | 
        /// </summary> 
 | 
        private void CopyToEntries(DictionaryEntry[] array, int index) 
 | 
        { 
 | 
            Node[] buckets = m_buckets; 
 | 
            for (int i = 0; i < buckets.Length; i++) 
 | 
            { 
 | 
                for (Node current = buckets[i]; current != null; current = current.m_next) 
 | 
                { 
 | 
                    array[index] = new DictionaryEntry(current.m_key, current.m_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 m_locks before calling CopyToObjects.  
 | 
        /// </summary> 
 | 
        private void CopyToObjects(object[] array, int index) 
 | 
        { 
 | 
            Node[] buckets = m_buckets; 
 | 
            for (int i = 0; i < buckets.Length; i++) 
 | 
            { 
 | 
                for (Node current = buckets[i]; current != null; current = current.m_next) 
 | 
                { 
 | 
                    array[index] = new KeyValuePair<TKey, TValue>(current.m_key, current.m_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 = m_buckets; 
 | 
  
 | 
            for (int i = 0; i < buckets.Length; i++) 
 | 
            { 
 | 
                Node current = buckets[i]; 
 | 
  
 | 
                // The memory barrier ensures that the load of the fields of 'current' doesn’t move before the load from buckets[i].  
 | 
                Thread.MemoryBarrier(); 
 | 
                while (current != null) 
 | 
                { 
 | 
                    yield return new KeyValuePair<TKey, TValue>(current.m_key, current.m_value); 
 | 
                    current = current.m_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> 
 | 
        private bool TryAddInternal(TKey key, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue) 
 | 
        { 
 | 
            int hashcode = m_comparer.GetHashCode(key); 
 | 
  
 | 
            while (true) 
 | 
            { 
 | 
                int bucketNo, lockNo; 
 | 
  
 | 
                Node[] buckets = m_buckets; 
 | 
                GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, buckets.Length); 
 | 
  
 | 
                bool resizeDesired = false; 
 | 
                bool lockTaken = false; 
 | 
                try 
 | 
                { 
 | 
                    if (acquireLock) 
 | 
                    { 
 | 
                        Monitor.Enter(m_locks[lockNo]); 
 | 
                        lockTaken = true; 
 | 
                    } 
 | 
  
 | 
                    // If the table just got resized, we may not be holding the right lock, and must retry.  
 | 
                    // This should be a rare occurence.  
 | 
                    if (buckets != m_buckets) 
 | 
                    { 
 | 
                        continue; 
 | 
                    } 
 | 
  
 | 
                    // Try to find this key in the bucket  
 | 
                    Node prev = null; 
 | 
                    for (Node node = buckets[bucketNo]; node != null; node = node.m_next) 
 | 
                    { 
 | 
                        Assert((prev == null && node == m_buckets[bucketNo]) || prev.m_next == node); 
 | 
                        if (m_comparer.Equals(node.m_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) 
 | 
                            { 
 | 
                                Node newNode = new Node(node.m_key, value, hashcode, node.m_next); 
 | 
                                if (prev == null) 
 | 
                                { 
 | 
                                    buckets[bucketNo] = newNode; 
 | 
                                } 
 | 
                                else 
 | 
                                { 
 | 
                                    prev.m_next = newNode; 
 | 
                                } 
 | 
                                resultingValue = value; 
 | 
                            } 
 | 
                            else 
 | 
                            { 
 | 
                                resultingValue = node.m_value; 
 | 
                            } 
 | 
                            return false; 
 | 
                        } 
 | 
                        prev = node; 
 | 
                    } 
 | 
  
 | 
                    // The key was not found in the bucket. Insert the key-value pair.  
 | 
                    buckets[bucketNo] = new Node(key, value, hashcode, buckets[bucketNo]); 
 | 
                    checked 
 | 
                    { 
 | 
                        m_countPerLock[lockNo]++; 
 | 
                    } 
 | 
  
 | 
                    //  
 | 
                    // If this lock has element / bucket ratio greater than 1, resize the entire table. 
 | 
                    // Note: the formula is chosen to avoid overflow, but has a small inaccuracy due to  
 | 
                    // rounding. 
 | 
                    // 
 | 
                    if (m_countPerLock[lockNo] > buckets.Length / m_locks.Length) 
 | 
                    { 
 | 
                        resizeDesired = true; 
 | 
                    } 
 | 
                } 
 | 
                finally 
 | 
                { 
 | 
                    if (lockTaken) 
 | 
                        Monitor.Exit(m_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(buckets); 
 | 
                } 
 | 
  
 | 
                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:Sytem.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)) 
 | 
                { 
 | 
                    throw new KeyNotFoundException(); 
 | 
                } 
 | 
                return value; 
 | 
            } 
 | 
            set 
 | 
            { 
 | 
                if (key == null) 
 | 
                    throw new ArgumentNullException("key"); 
 | 
                TValue dummy; 
 | 
                TryAddInternal(key, value, true, true, out dummy); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <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 paris 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 
 | 
        { 
 | 
            get 
 | 
            { 
 | 
                int count = 0; 
 | 
  
 | 
                int acquiredLocks = 0; 
 | 
                try 
 | 
                { 
 | 
                    // Acquire all locks 
 | 
                    AcquireAllLocks(ref acquiredLocks); 
 | 
  
 | 
                    // Compute the count, we allow overflow  
 | 
                    for (int i = 0; i < m_countPerLock.Length; i++) 
 | 
                    { 
 | 
                        count += m_countPerLock[i]; 
 | 
                    } 
 | 
  
 | 
                } 
 | 
                finally 
 | 
                { 
 | 
                    // Release locks that have been acquired earlier  
 | 
                    ReleaseLocks(0, acquiredLocks); 
 | 
                } 
 | 
  
 | 
                return count; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/>  
 | 
        /// if the key does not already exist.  
 | 
        /// </summary> 
 | 
        /// <param name="key">The key of the element to add.</param>  
 | 
        /// <param name="valueFactory">The function used to generate a value for the key</param> 
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference 
 | 
        /// (Nothing in Visual Basic).</exception> 
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="valueFactory"/> is a null reference  
 | 
        /// (Nothing in Visual Basic).</exception> 
 | 
        /// <exception cref="T:System.OverflowException">The dictionary contains too many  
 | 
        /// elements.</exception>  
 | 
        /// <returns>The value for the key.  This will be either the existing value for the key if the 
 | 
        /// key is already in the dictionary, or the new value for the key as returned by valueFactory  
 | 
        /// if the key was not in the dictionary.</returns> 
 | 
        public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) 
 | 
        { 
 | 
            if (key == null) 
 | 
                throw new ArgumentNullException("key"); 
 | 
            if (valueFactory == null) 
 | 
                throw new ArgumentNullException("valueFactory"); 
 | 
  
 | 
            TValue resultingValue; 
 | 
            if (TryGetValue(key, out resultingValue)) 
 | 
            { 
 | 
                return resultingValue; 
 | 
            } 
 | 
            TryAddInternal(key, valueFactory(key), false, true, out resultingValue); 
 | 
            return resultingValue; 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> 
 | 
        /// if the key does not already exist.  
 | 
        /// </summary> 
 | 
        /// <param name="key">The key of the element to add.</param> 
 | 
        /// <param name="value">the value to be added, if the key does not already exist</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>  
 | 
        /// <returns>The value for the key.  This will be either the existing value for the key if the 
 | 
        /// key is already in the dictionary, or the new value if the key was not in the dictionary.</returns>  
 | 
        public TValue GetOrAdd(TKey key, TValue value) 
 | 
        { 
 | 
            if (key == null) 
 | 
                throw new ArgumentNullException("key"); 
 | 
  
 | 
            TValue resultingValue; 
 | 
            TryAddInternal(key, value, false, true, out resultingValue); 
 | 
            return resultingValue; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key does not already 
 | 
        /// exist, or updates a key/value pair in the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key 
 | 
        /// already exists.  
 | 
        /// </summary> 
 | 
        /// <param name="key">The key to be added or whose value should be updated</param>  
 | 
        /// <param name="addValueFactory">The function used to generate a value for an absent key</param>  
 | 
        /// <param name="updateValueFactory">The function used to generate a new value for an existing key 
 | 
        /// based on the key's existing value</param>  
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference 
 | 
        /// (Nothing in Visual Basic).</exception> 
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="addValueFactory"/> is a null reference 
 | 
        /// (Nothing in Visual Basic).</exception>  
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="updateValueFactory"/> is a null reference 
 | 
        /// (Nothing in Visual Basic).</exception>  
 | 
        /// <exception cref="T:System.OverflowException">The dictionary contains too many  
 | 
        /// elements.</exception> 
 | 
        /// <returns>The new value for the key.  This will be either be the result of addValueFactory (if the key was  
 | 
        /// absent) or the result of updateValueFactory (if the key was present).</returns> 
 | 
        public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory) 
 | 
        { 
 | 
            if (key == null) 
 | 
                throw new ArgumentNullException("key"); 
 | 
            if (addValueFactory == null) 
 | 
                throw new ArgumentNullException("addValueFactory"); 
 | 
            if (updateValueFactory == null) 
 | 
                throw new ArgumentNullException("updateValueFactory"); 
 | 
  
 | 
            TValue newValue, resultingValue; 
 | 
            while (true) 
 | 
            { 
 | 
                TValue oldValue; 
 | 
                if (TryGetValue(key, out oldValue)) 
 | 
                {                //key exists, try to update  
 | 
                    newValue = updateValueFactory(key, oldValue); 
 | 
                    if (TryUpdate(key, newValue, oldValue)) 
 | 
                    { 
 | 
                        return newValue; 
 | 
                    } 
 | 
                } 
 | 
                else 
 | 
                { //try add 
 | 
                    newValue = addValueFactory(key); 
 | 
                    if (TryAddInternal(key, newValue, false, true, out resultingValue)) 
 | 
                    { 
 | 
                        return resultingValue; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key does not already  
 | 
        /// exist, or updates a key/value pair in the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key  
 | 
        /// already exists. 
 | 
        /// </summary>  
 | 
        /// <param name="key">The key to be added or whose value should be updated</param> 
 | 
        /// <param name="addValue">The value to be added for an absent key</param> 
 | 
        /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on 
 | 
        /// the key's existing value</param>  
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference 
 | 
        /// (Nothing in Visual Basic).</exception>  
 | 
        /// <exception cref="T:System.ArgumentNullException"><paramref name="updateValueFactory"/> is a null reference  
 | 
        /// (Nothing in Visual Basic).</exception> 
 | 
        /// <exception cref="T:System.OverflowException">The dictionary contains too many  
 | 
        /// elements.</exception> 
 | 
        /// <returns>The new value for the key.  This will be either be the result of addValueFactory (if the key was 
 | 
        /// absent) or the result of updateValueFactory (if the key was present).</returns> 
 | 
        public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory) 
 | 
        { 
 | 
            if (key == null) 
 | 
                throw new ArgumentNullException("key"); 
 | 
            if (updateValueFactory == null) 
 | 
                throw new ArgumentNullException("updateValueFactory"); 
 | 
            TValue newValue, resultingValue; 
 | 
            while (true) 
 | 
            { 
 | 
                TValue oldValue; 
 | 
                if (TryGetValue(key, out oldValue)) 
 | 
                {                //key exists, try to update  
 | 
                    newValue = updateValueFactory(key, oldValue); 
 | 
                    if (TryUpdate(key, newValue, oldValue)) 
 | 
                    { 
 | 
                        return newValue; 
 | 
                    } 
 | 
                } 
 | 
                else 
 | 
                { //try add 
 | 
                    if (TryAddInternal(key, addValue, false, true, out resultingValue)) 
 | 
                    { 
 | 
                        return resultingValue; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
  
 | 
  
 | 
        /// <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 
 | 
        { 
 | 
            get 
 | 
            { 
 | 
                int acquiredLocks = 0; 
 | 
                try 
 | 
                { 
 | 
                    // Acquire all locks  
 | 
                    AcquireAllLocks(ref acquiredLocks); 
 | 
  
 | 
                    for (int i = 0; i < m_countPerLock.Length; i++) 
 | 
                    { 
 | 
                        if (m_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)) 
 | 
            { 
 | 
                throw new ArgumentException(GetResource("ConcurrentDictionary_KeyAlreadyExisted")); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <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 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(); } 
 | 
        } 
 | 
  
 | 
        #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) 
 | 
                throw new ArgumentNullException(GetResource("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) 
 | 
                throw new ArgumentNullException("key"); 
 | 
            if (!(key is TKey)) 
 | 
                throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect")); 
 | 
  
 | 
            TValue typedValue; 
 | 
            try 
 | 
            { 
 | 
                typedValue = (TValue)value; 
 | 
            } 
 | 
            catch (InvalidCastException) 
 | 
            { 
 | 
                throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect")); 
 | 
            } 
 | 
  
 | 
            ((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) 
 | 
                throw new ArgumentNullException("key"); 
 | 
  
 | 
            return (key is TKey) && ((ConcurrentDictionary<TKey, TValue>)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) 
 | 
                throw new ArgumentNullException("key"); 
 | 
  
 | 
            TValue throwAwayValue; 
 | 
            if (key is TKey) 
 | 
            { 
 | 
                this.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) 
 | 
                    throw new ArgumentNullException("key"); 
 | 
  
 | 
                TValue value; 
 | 
                if (key is TKey && this.TryGetValue((TKey)key, out value)) 
 | 
                { 
 | 
                    return value; 
 | 
                } 
 | 
  
 | 
                return null; 
 | 
            } 
 | 
            set 
 | 
            { 
 | 
                if (key == null) 
 | 
                    throw new ArgumentNullException("key"); 
 | 
  
 | 
                if (!(key is TKey)) 
 | 
                    throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect")); 
 | 
                if (!(value is TValue)) 
 | 
                    throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect")); 
 | 
  
 | 
                ((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> 
 | 
        void ICollection.CopyTo(Array array, int index) 
 | 
        { 
 | 
            if (array == null) 
 | 
                throw new ArgumentNullException("array"); 
 | 
            if (index < 0) 
 | 
                throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative")); 
 | 
  
 | 
            int locksAcquired = 0; 
 | 
            try 
 | 
            { 
 | 
                AcquireAllLocks(ref locksAcquired); 
 | 
  
 | 
                int count = 0; 
 | 
  
 | 
                for (int i = 0; i < m_locks.Length; i++) 
 | 
                { 
 | 
                    count += m_countPerLock[i]; 
 | 
                } 
 | 
  
 | 
                if (array.Length - count < index || count < 0) 
 | 
                { //"count" itself or "count + index" can overflow 
 | 
                    throw new ArgumentException(GetResource("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; 
 | 
                } 
 | 
  
 | 
                throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayIncorrectType"), "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 
 | 
            { 
 | 
                throw new NotSupportedException(); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        #endregion 
 | 
  
 | 
        /// <summary>  
 | 
        /// Replaces the internal table with a larger one. To prevent multiple threads from resizing the  
 | 
        /// table as a result of ----s, the table of buckets that was deemed too small is passed in as 
 | 
        /// an argument to GrowTable(). GrowTable() obtains a lock, and then checks whether the bucket  
 | 
        /// table has been replaced in the meantime or not. 
 | 
        /// </summary> 
 | 
        /// <param name="buckets">Reference to the bucket table that was deemed too small.</param> 
 | 
        private void GrowTable(Node[] buckets) 
 | 
        { 
 | 
            int locksAcquired = 0; 
 | 
            try 
 | 
            { 
 | 
                // The thread that first obtains m_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 (buckets != m_buckets) 
 | 
                { 
 | 
                    // We assume that since the table reference is different, it was already resized. 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 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; 
 | 
                try 
 | 
                { 
 | 
                    checked 
 | 
                    { 
 | 
                        // Double the size of the buckets table and add one, so that we have an odd integer. 
 | 
                        newLength = 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; 
 | 
                        } 
 | 
  
 | 
                        Assert(newLength % 2 != 0); 
 | 
                    } 
 | 
                } 
 | 
                catch (OverflowException) 
 | 
                { 
 | 
                    // If we were to resize the table, its new size will not fit into a 32-bit signed int. Just return.  
 | 
                    return; 
 | 
                } 
 | 
  
 | 
                Node[] newBuckets = new Node[newLength]; 
 | 
                int[] newCountPerLock = new int[m_locks.Length]; 
 | 
  
 | 
                // Now acquire all other locks for the table 
 | 
                AcquireLocks(1, m_locks.Length, ref locksAcquired); 
 | 
  
 | 
                // Copy all data into a new table, creating new nodes for all elements 
 | 
                for (int i = 0; i < buckets.Length; i++) 
 | 
                { 
 | 
                    Node current = buckets[i]; 
 | 
                    while (current != null) 
 | 
                    { 
 | 
                        Node next = current.m_next; 
 | 
                        int newBucketNo, newLockNo; 
 | 
                        GetBucketAndLockNo(current.m_hashcode, out newBucketNo, out newLockNo, newBuckets.Length); 
 | 
  
 | 
                        newBuckets[newBucketNo] = new Node(current.m_key, current.m_value, current.m_hashcode, newBuckets[newBucketNo]); 
 | 
  
 | 
                        checked 
 | 
                        { 
 | 
                            newCountPerLock[newLockNo]++; 
 | 
                        } 
 | 
  
 | 
                        current = next; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                // And finally adjust m_buckets and m_countPerLock to point to data for the new table 
 | 
                m_buckets = newBuckets; 
 | 
                m_countPerLock = newCountPerLock; 
 | 
  
 | 
            } 
 | 
            finally 
 | 
            { 
 | 
                // Release all locks that we took earlier  
 | 
                ReleaseLocks(0, locksAcquired); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Computes the bucket and lock number for a particular key.  
 | 
        /// </summary>  
 | 
        private void GetBucketAndLockNo( 
 | 
            int hashcode, out int bucketNo, out int lockNo, int bucketCount) 
 | 
        { 
 | 
            bucketNo = (hashcode & 0x7fffffff) % bucketCount; 
 | 
            lockNo = bucketNo % m_locks.Length; 
 | 
  
 | 
            Assert(bucketNo >= 0 && bucketNo < bucketCount); 
 | 
            Assert(lockNo >= 0 && lockNo < m_locks.Length); 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// The number of concurrent writes for which to optimize by default. 
 | 
        /// </summary> 
 | 
        private static int DefaultConcurrencyLevel 
 | 
        { 
 | 
  
 | 
            get { return DEFAULT_CONCURRENCY_MULTIPLIER * Environment.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) 
 | 
        { 
 | 
            AcquireLocks(0, m_locks.Length, ref locksAcquired); 
 | 
            Assert(locksAcquired == m_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) 
 | 
        { 
 | 
            Assert(fromInclusive <= toExclusive); 
 | 
  
 | 
            for (int i = fromInclusive; i < toExclusive; i++) 
 | 
            { 
 | 
                bool lockTaken = false; 
 | 
                try 
 | 
                { 
 | 
                    Monitor.Enter(m_locks[i]); 
 | 
                    lockTaken = true; 
 | 
                } 
 | 
                finally 
 | 
                { 
 | 
                    if (lockTaken) 
 | 
                    { 
 | 
                        locksAcquired++; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Releases a contiguous range of locks. 
 | 
        /// </summary>  
 | 
        private void ReleaseLocks(int fromInclusive, int toExclusive) 
 | 
        { 
 | 
            Assert(fromInclusive <= toExclusive); 
 | 
  
 | 
            for (int i = fromInclusive; i < toExclusive; i++) 
 | 
            { 
 | 
                Monitor.Exit(m_locks[i]); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Gets a collection containing the keys in the dictionary.  
 | 
        /// </summary> 
 | 
        private ReadOnlyCollection<TKey> GetKeys() 
 | 
        { 
 | 
            int locksAcquired = 0; 
 | 
            try 
 | 
            { 
 | 
                AcquireAllLocks(ref locksAcquired); 
 | 
                List<TKey> keys = new List<TKey>(); 
 | 
  
 | 
                for (int i = 0; i < m_buckets.Length; i++) 
 | 
                { 
 | 
                    Node current = m_buckets[i]; 
 | 
                    while (current != null) 
 | 
                    { 
 | 
                        keys.Add(current.m_key); 
 | 
                        current = current.m_next; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                return new ReadOnlyCollection<TKey>(keys); 
 | 
            } 
 | 
            finally 
 | 
            { 
 | 
                ReleaseLocks(0, locksAcquired); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Gets a collection containing the values in the dictionary. 
 | 
        /// </summary> 
 | 
        private ReadOnlyCollection<TValue> GetValues() 
 | 
        { 
 | 
            int locksAcquired = 0; 
 | 
            try 
 | 
            { 
 | 
                AcquireAllLocks(ref locksAcquired); 
 | 
                List<TValue> values = new List<TValue>(); 
 | 
  
 | 
                for (int i = 0; i < m_buckets.Length; i++) 
 | 
                { 
 | 
                    Node current = m_buckets[i]; 
 | 
                    while (current != null) 
 | 
                    { 
 | 
                        values.Add(current.m_value); 
 | 
                        current = current.m_next; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                return new ReadOnlyCollection<TValue>(values); 
 | 
            } 
 | 
            finally 
 | 
            { 
 | 
                ReleaseLocks(0, locksAcquired); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// A helper method for asserts.  
 | 
        /// </summary> 
 | 
        [Conditional("DEBUG")] 
 | 
        private void Assert(bool condition) 
 | 
        { 
 | 
            if (!condition) 
 | 
            { 
 | 
                throw new Exception("Assertion failed."); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// A helper function to obtain the string for a particular resource key. 
 | 
        /// </summary> 
 | 
        /// <param name="key"></param>  
 | 
        /// <returns></returns> 
 | 
        private string GetResource(string key) 
 | 
        { 
 | 
            Assert(key != null); 
 | 
  
 | 
            return key; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// A node in a singly-linked list representing a particular hash table bucket.  
 | 
        /// </summary> 
 | 
        private class Node 
 | 
        { 
 | 
            internal TKey m_key; 
 | 
            internal TValue m_value; 
 | 
            internal volatile Node m_next; 
 | 
            internal int m_hashcode; 
 | 
  
 | 
            internal Node(TKey key, TValue value, int hashcode) 
 | 
                : this(key, value, hashcode, null) 
 | 
            { 
 | 
            } 
 | 
  
 | 
            internal Node(TKey key, TValue value, int hashcode, Node next) 
 | 
            { 
 | 
                m_key = key; 
 | 
                m_value = value; 
 | 
                m_next = next; 
 | 
                m_hashcode = hashcode; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// A private class to represent enumeration over the dictionary that implements the  
 | 
        /// IDictionaryEnumerator interface.  
 | 
        /// </summary> 
 | 
        private class DictionaryEnumerator : IDictionaryEnumerator 
 | 
        { 
 | 
            IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator; 
 | 
            // Enumerator over the dictionary. 
 | 
  
 | 
            internal DictionaryEnumerator(ConcurrentDictionary<TKey, TValue> dictionary) 
 | 
            { 
 | 
                m_enumerator = dictionary.GetEnumerator(); 
 | 
            } 
 | 
  
 | 
            public DictionaryEntry Entry 
 | 
            { 
 | 
                get { return new DictionaryEntry(m_enumerator.Current.Key, m_enumerator.Current.Value); } 
 | 
            } 
 | 
  
 | 
            public object Key 
 | 
            { 
 | 
                get { return m_enumerator.Current.Key; } 
 | 
            } 
 | 
  
 | 
            public object Value 
 | 
            { 
 | 
                get { return m_enumerator.Current.Value; } 
 | 
            } 
 | 
  
 | 
            public object Current 
 | 
            { 
 | 
                get { return this.Entry; } 
 | 
            } 
 | 
  
 | 
            public bool MoveNext() 
 | 
            { 
 | 
                return m_enumerator.MoveNext(); 
 | 
            } 
 | 
  
 | 
            public void Reset() 
 | 
            { 
 | 
                m_enumerator.Reset(); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Get the data array to be serialized 
 | 
        /// </summary>  
 | 
        [OnSerializing] 
 | 
        private void OnSerializing(StreamingContext context) 
 | 
        { 
 | 
            // save the data into the serialization array to be saved 
 | 
            m_serializationArray = ToArray(); 
 | 
            m_serializationConcurrencyLevel = m_locks.Length; 
 | 
            m_serializationCapacity = m_buckets.Length; 
 | 
        } 
 | 
  
 | 
        /// <summary>  
 | 
        /// Construct the dictionary from a previously seiralized one 
 | 
        /// </summary>  
 | 
        [OnDeserialized] 
 | 
        private void OnDeserialized(StreamingContext context) 
 | 
        { 
 | 
            KeyValuePair<TKey, TValue>[] array = m_serializationArray; 
 | 
  
 | 
            m_buckets = new Node[m_serializationCapacity]; 
 | 
            m_countPerLock = new int[m_serializationConcurrencyLevel]; 
 | 
  
 | 
            m_locks = new object[m_serializationConcurrencyLevel]; 
 | 
            for (int i = 0; i < m_locks.Length; i++) 
 | 
            { 
 | 
                m_locks[i] = new object(); 
 | 
            } 
 | 
  
 | 
            InitializeFromCollection(array); 
 | 
            m_serializationArray = null; 
 | 
  
 | 
        } 
 | 
    } 
 | 
} 
 | 
  
 | 
#endif 
 |