summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs')
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs375
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>