diff options
Diffstat (limited to 'src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs')
-rw-r--r-- | src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs | 375 |
1 files changed, 1 insertions, 374 deletions
diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs index c1a6f7564c..8b9014a103 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -24,7 +24,6 @@ using System.Runtime.Serialization; using System.Text; using System.Threading; using System.Security; -using System.Security.Permissions; namespace System.Collections.Concurrent { @@ -37,10 +36,9 @@ namespace System.Collections.Concurrent /// All public and protected members of <see cref="ConcurrentDictionary{TKey,TValue}"/> are thread-safe and may be used /// concurrently from multiple threads. /// </remarks> - [ComVisible(false)] [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))] [DebuggerDisplay("Count = {Count}")] - public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue> + internal class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue> { /// <summary> /// Tables that hold the internal state of the ConcurrentDictionary @@ -139,149 +137,6 @@ namespace System.Collections.Concurrent /// </summary> public ConcurrentDictionary() : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, true, 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 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, false, 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, true, 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(comparer) - { - if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); - - InitializeFromCollection(collection); - } - - /// <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, false, comparer) - { - if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); - if (comparer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparer); - - InitializeFromCollection(collection); - } - - private void InitializeFromCollection(IEnumerable<KeyValuePair<TKey, TValue>> collection) - { - TValue dummy; - foreach (KeyValuePair<TKey, TValue> pair in collection) - { - if (pair.Key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - - if (!TryAddInternal(pair.Key, pair.Value, false, false, out dummy)) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_SourceContainsDuplicateKeys); - } - } - - if (m_budget == 0) - { - m_budget = m_tables.m_buckets.Length / m_tables.m_locks.Length; - } - - } - - /// <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) - : this(concurrencyLevel, capacity, false, comparer) - { - } - internal ConcurrentDictionary(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer<TKey> comparer) { if (concurrencyLevel < 1) @@ -488,91 +343,6 @@ namespace System.Collections.Concurrent } /// <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> - [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")] - public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue) - { - if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - - IEqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default; - - while (true) - { - int bucketNo; - int lockNo; - int hashcode; - - Tables tables = m_tables; - IEqualityComparer<TKey> comparer = tables.m_comparer; - - hashcode = comparer.GetHashCode(key); - GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, tables.m_buckets.Length, tables.m_locks.Length); - - lock (tables.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 (tables != m_tables) - { - continue; - } - - // Try to find this key in the bucket - Node prev = null; - for (Node node = tables.m_buckets[bucketNo]; node != null; node = node.m_next) - { - Assert((prev == null && node == tables.m_buckets[bucketNo]) || prev.m_next == node); - if (comparer.Equals(node.m_key, key)) - { - if (valueComparer.Equals(node.m_value, comparisonValue)) - { - if (s_isValueWriteAtomic) - { - node.m_value = newValue; - } - else - { - Node newNode = new Node(node.m_key, newValue, hashcode, node.m_next); - - if (prev == null) - { - tables.m_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() @@ -947,149 +717,6 @@ namespace System.Collections.Concurrent } } - /// <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) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - if (valueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.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) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.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) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - if (addValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.addValueFactory); - if (updateValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.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) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - if (updateValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.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> |