1413 lines · 71.6 KB · C#
RawDownload
#if MONOusing System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Diagnostics;using System.Runtime;using System.Runtime.InteropServices;using System.Runtime.Serialization;using System.Security.Permissions;using System.Threading;namespace System.Collections.Concurrent{    /// <summary>Represents a thread-safe collection of key-value pairs that can be accessed by multiple threads concurrently. </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>    [__DynamicallyInvokable, DebuggerDisplay("Count = {Count}"), ComVisible(false)]    [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]    [Serializable]    public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable    {        private class Tables        {            internal readonly ConcurrentDictionary<TKey, TValue>.Node[] m_buckets;            internal readonly object[] m_locks;            internal volatile int[] m_countPerLock;            internal Tables(ConcurrentDictionary<TKey, TValue>.Node[] buckets, object[] locks, int[] countPerLock)            {                this.m_buckets = buckets;                this.m_locks = locks;                this.m_countPerLock = countPerLock;            }        }        private class Node        {            internal TKey m_key;            internal TValue m_value;            internal volatile ConcurrentDictionary<TKey, TValue>.Node m_next;            internal int m_hashcode;            internal Node(TKey key, TValue value, int hashcode, ConcurrentDictionary<TKey, TValue>.Node next)            {                this.m_key = key;                this.m_value = value;                this.m_next = next;                this.m_hashcode = hashcode;            }        }        private class DictionaryEnumerator : IDictionaryEnumerator, IEnumerator        {            private IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator;            public DictionaryEntry Entry            {                get                {                    KeyValuePair<TKey, TValue> current = this.m_enumerator.Current;                    object arg_30_0 = current.Key;                    KeyValuePair<TKey, TValue> current2 = this.m_enumerator.Current;                    return new DictionaryEntry(arg_30_0, current2.Value);                }            }            public object Key            {                get                {                    KeyValuePair<TKey, TValue> current = this.m_enumerator.Current;                    return current.Key;                }            }            public object Value            {                get                {                    KeyValuePair<TKey, TValue> current = this.m_enumerator.Current;                    return current.Value;                }            }            public object Current            {                get                {                    return this.Entry;                }            }            internal DictionaryEnumerator(ConcurrentDictionary<TKey, TValue> dictionary)            {                this.m_enumerator = dictionary.GetEnumerator();            }            public bool MoveNext()            {                return this.m_enumerator.MoveNext();            }            public void Reset()            {                this.m_enumerator.Reset();            }        }        [NonSerialized]        private volatile ConcurrentDictionary<TKey, TValue>.Tables m_tables;        private readonly IEqualityComparer<TKey> m_comparer;        [NonSerialized]        private readonly bool m_growLockArray;        [NonSerialized]        private int m_budget;        private KeyValuePair<TKey, TValue>[] m_serializationArray;        private int m_serializationConcurrencyLevel;        private int m_serializationCapacity;        private static readonly bool s_isValueWriteAtomic = ConcurrentDictionary<TKey, TValue>.IsValueWriteAtomic();        private const int DEFAULT_CONCURRENCY_MULTIPLIER = 4;        private const int DEFAULT_CAPACITY = 31;        private const int MAX_LOCK_NUMBER = 1024;        /// <summary>Gets or sets the value associated with the specified key.</summary>        /// <returns>Returns the Value property of the <see cref="T:System.Collections.Generic.KeyValuePair`2" /> at the specified index.</returns>        /// <param name="key">The key of the value to get or set.</param>        /// <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>        [__DynamicallyInvokable]        public TValue this[TKey key]        {            [__DynamicallyInvokable]            get            {                TValue result;                if (!this.TryGetValue(key, out result))                {                    throw new KeyNotFoundException();                }                return result;            }            [__DynamicallyInvokable]            set            {                if (key == null)                {                    throw new ArgumentNullException("key");                }                TValue tValue;                this.TryAddInternal(key, value, true, true, out tValue);            }        }        /// <summary>Gets the number of key/value pairs contained in the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" />.</summary>        /// <returns>The number of key/value pairs contained in the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" />.</returns>        /// <exception cref="T:System.OverflowException">The dictionary already contains the maximum number of elements, <see cref="F:System.Int32.MaxValue" />.</exception>        [__DynamicallyInvokable]        public int Count        {            [__DynamicallyInvokable]            get            {                int num = 0;                int toExclusive = 0;                try                {                    this.AcquireAllLocks(ref toExclusive);                    for (int i = 0; i < this.m_tables.m_countPerLock.Length; i++)                    {                        num += this.m_tables.m_countPerLock[i];                    }                }                finally                {                    this.ReleaseLocks(0, toExclusive);                }                return num;            }        }        /// <summary>Gets a value that indicates whether the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> is empty.</summary>        /// <returns>true if the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> is empty; otherwise, false.</returns>        [__DynamicallyInvokable]        public bool IsEmpty        {            [__DynamicallyInvokable]            get            {                int toExclusive = 0;                try                {                    this.AcquireAllLocks(ref toExclusive);                    for (int i = 0; i < this.m_tables.m_countPerLock.Length; i++)                    {                        if (this.m_tables.m_countPerLock[i] != 0)                        {                            return false;                        }                    }                }                finally                {                    this.ReleaseLocks(0, toExclusive);                }                return true;            }        }        /// <summary>Gets a collection containing the keys in the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}" />.</summary>        /// <returns>An <see cref="T:System.Collections.Generic.ICollection{TKey}" /> containing the keys in the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}" />.</returns>        [__DynamicallyInvokable]        public ICollection<TKey> Keys        {            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]            get            {                return this.GetKeys();            }        }        /// <summary>Gets a collection containing the values in the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}" />.</summary>        /// <returns>An <see cref="T:System.Collections.Generic.ICollection{TValue}" /> containing the values in the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}" />.</returns>        [__DynamicallyInvokable]        public ICollection<TValue> Values        {            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]            get            {                return this.GetValues();            }        }        [__DynamicallyInvokable]        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly        {            [__DynamicallyInvokable]            get            {                return false;            }        }        /// <summary>Gets a value indicating whether the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}" /> has a fixed size.</summary>        /// <returns>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.</returns>        [__DynamicallyInvokable]        bool IDictionary.IsFixedSize        {            [__DynamicallyInvokable]            get            {                return false;            }        }        /// <summary>Gets a value indicating whether the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}" /> is read-only.</summary>        /// <returns>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.</returns>        [__DynamicallyInvokable]        bool IDictionary.IsReadOnly        {            [__DynamicallyInvokable]            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>        /// <returns>An <see cref="T:System.Collections.ICollection" /> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}" />.</returns>        [__DynamicallyInvokable]        ICollection IDictionary.Keys        {            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]            get            {                return this.GetKeys();            }        }        /// <summary>Gets an <see cref="T:System.Collections.ICollection" /> containing the values in the <see cref="T:System.Collections.IDictionary" />.</summary>        /// <returns>An <see cref="T:System.Collections.ICollection" /> containing the values in the <see cref="T:System.Collections.IDictionary" />.</returns>        [__DynamicallyInvokable]        ICollection IDictionary.Values        {            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]            get            {                return this.GetValues();            }        }        /// <summary>Gets or sets the value associated with the specified key.</summary>        /// <returns>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  of the <see cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}" />.</returns>        /// <param name="key">The key of the value to get or set.</param>        /// <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  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  of the <see cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}" /></exception>        [__DynamicallyInvokable]        object IDictionary.this[object key]        {            [__DynamicallyInvokable]            get            {                if (key == null)                {                    throw new ArgumentNullException("key");                }                TValue tValue;                if (key is TKey && this.TryGetValue((TKey)((object)key), out tValue))                {                    return tValue;                }                return null;            }            [__DynamicallyInvokable]            set            {                if (key == null)                {                    throw new ArgumentNullException("key");                }                if (!(key is TKey))                {                    throw new ArgumentException(this.GetResource("ConcurrentDictionary_TypeOfKeyIncorrect"));                }                if (!(value is TValue))                {                    throw new ArgumentException(this.GetResource("ConcurrentDictionary_TypeOfValueIncorrect"));                }                this[(TKey)((object)key)] = (TValue)((object)value);            }        }        /// <summary>Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection" /> is synchronized with the SyncRoot.</summary>        /// <returns>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.</returns>        [__DynamicallyInvokable]        bool ICollection.IsSynchronized        {            [__DynamicallyInvokable]            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>        /// <returns>Always returns null.</returns>        /// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported.</exception>        [__DynamicallyInvokable]        object ICollection.SyncRoot        {            [__DynamicallyInvokable]            get            {                throw new NotSupportedException("ConcurrentCollection_SyncRoot_NotSupported");            }        }        private static int DefaultConcurrencyLevel        {            get            {                return 4 * PlatformHelper.ProcessorCount;            }        }        private static bool IsValueWriteAtomic()        {            Type typeFromHandle = typeof(TValue);            bool flag = typeFromHandle.IsClass || typeFromHandle == typeof(bool) || typeFromHandle == typeof(char) || typeFromHandle == typeof(byte) || typeFromHandle == typeof(sbyte) || typeFromHandle == typeof(short) || typeFromHandle == typeof(ushort) || typeFromHandle == typeof(int) || typeFromHandle == typeof(uint) || typeFromHandle == typeof(float);            if (!flag && IntPtr.Size == 8)            {                flag |= (typeFromHandle == typeof(double) || typeFromHandle == typeof(long));            }            return flag;        }        /// <summary>Initializes a new instance of the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> class that is empty, has the default concurrency level, has the default initial capacity, and uses the default comparer for the key type.</summary>        [__DynamicallyInvokable]        public ConcurrentDictionary()            : this(ConcurrentDictionary<TKey, TValue>.DefaultConcurrencyLevel, 31, true, EqualityComparer<TKey>.Default)        {        }        /// <summary>Initializes a new instance of the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> 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="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> concurrently.</param>        /// <param name="capacity">The initial number of elements that the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> can contain.</param>        /// <exception cref="T:System.ArgumentOutOfRangeException">        ///   <paramref name="concurrencyLevel" /> is less than 1.-or-<paramref name="capacity" /> is less than 0.</exception>        [__DynamicallyInvokable]        public ConcurrentDictionary(int concurrencyLevel, int capacity)            : this(concurrencyLevel, capacity, false, EqualityComparer<TKey>.Default)        {        }        /// <summary>Initializes a new instance of the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> 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="T:System.Collections.Concurrent.ConcurrentDictionary`2" />.</param>        /// <exception cref="T:System.ArgumentNullException">        ///   <paramref name="collection" /> or any of its keys is a null reference (Nothing in Visual Basic)</exception>        /// <exception cref="T:System.ArgumentException">        ///   <paramref name="collection" /> contains one or more duplicate keys.</exception>        [__DynamicallyInvokable]        public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection)            : this(collection, EqualityComparer<TKey>.Default)        {        }        /// <summary>Initializes a new instance of the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> class that is empty, has the default 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>        [__DynamicallyInvokable]        public ConcurrentDictionary(IEqualityComparer<TKey> comparer)            : this(ConcurrentDictionary<TKey, TValue>.DefaultConcurrencyLevel, 31, true, comparer)        {        }        /// <summary>Initializes a new instance of the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> 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="T:System.Collections.Concurrent.ConcurrentDictionary`2" />.</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>        [__DynamicallyInvokable]        public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)            : this(comparer)        {            if (collection == null)            {                throw new ArgumentNullException("collection");            }            this.InitializeFromCollection(collection);        }        /// <summary>Initializes a new instance of the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> class that contains elements copied from the specified <see cref="T:System.Collections.IEnumerable" />, 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="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> concurrently.</param>        /// <param name="collection">The <see cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}" /> whose elements are copied to the new <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" />.</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>        [__DynamicallyInvokable]        public ConcurrentDictionary(int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)            : this(concurrencyLevel, 31, false, comparer)        {            if (collection == null)            {                throw new ArgumentNullException("collection");            }            if (comparer == null)            {                throw new ArgumentNullException("comparer");            }            this.InitializeFromCollection(collection);        }        private void InitializeFromCollection(IEnumerable<KeyValuePair<TKey, TValue>> collection)        {            foreach (KeyValuePair<TKey, TValue> current in collection)            {                if (current.Key == null)                {                    throw new ArgumentNullException("key");                }                TValue tValue;                if (!this.TryAddInternal(current.Key, current.Value, false, false, out tValue))                {                    throw new ArgumentException(this.GetResource("ConcurrentDictionary_SourceContainsDuplicateKeys"));                }            }            if (this.m_budget == 0)            {                this.m_budget = this.m_tables.m_buckets.Length / this.m_tables.m_locks.Length;            }        }        /// <summary>Initializes a new instance of the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> 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="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> concurrently.</param>        /// <param name="capacity">The initial number of elements that the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> 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.ArgumentNullException">        ///   <paramref name="comparer" /> is a null reference (Nothing in Visual Basic).</exception>        /// <exception cref="T:System.ArgumentOutOfRangeException">        ///   <paramref name="concurrencyLevel" /> is less than 1. -or- <paramref name="capacity" /> is less than 0.</exception>        [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]        public ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer)            : this(concurrencyLevel, capacity, false, comparer)        {        }        internal ConcurrentDictionary(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer<TKey> comparer)        {            if (concurrencyLevel < 1)            {                throw new ArgumentOutOfRangeException("concurrencyLevel", this.GetResource("ConcurrentDictionary_ConcurrencyLevelMustBePositive"));            }            if (capacity < 0)            {                throw new ArgumentOutOfRangeException("capacity", this.GetResource("ConcurrentDictionary_CapacityMustNotBeNegative"));            }            if (comparer == null)            {                throw new ArgumentNullException("comparer");            }            if (capacity < concurrencyLevel)            {                capacity = concurrencyLevel;            }            object[] array = new object[concurrencyLevel];            for (int i = 0; i < array.Length; i++)            {                array[i] = new object();            }            int[] countPerLock = new int[array.Length];            ConcurrentDictionary<TKey, TValue>.Node[] array2 = new ConcurrentDictionary<TKey, TValue>.Node[capacity];            this.m_tables = new ConcurrentDictionary<TKey, TValue>.Tables(array2, array, countPerLock);            this.m_comparer = comparer;            this.m_growLockArray = growLockArray;            this.m_budget = array2.Length / array.Length;        }        /// <summary>Attempts to add the specified key and value to the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" />.</summary>        /// <returns>true if the key/value pair was added to the <see cref="T:System.Collections.Concurrent.ConcurrentDictionary`2" /> successfully. If the key already exists, this method returns false.</returns>        /// <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>        /// <exception cref="T:System.ArgumentNullException">        ///   <paramref name="key" /> is null reference (Nothing in Visual Basic).</exception>        /// <exception cref="T:System.OverflowException">The dictionary already contains the maximum number of elements, <see cref="F:System.Int32.MaxValue" />.</exception>        [__DynamicallyInvokable]        public bool TryAdd(TKey key, TValue value)        {            if (key == null)            {                throw new ArgumentNullException("key");            }            TValue tValue;

Lines 1–500 of 1413.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t