From ba24a4a15c0317ac2fd954f4173b4b79cbdf191e Mon Sep 17 00:00:00 2001
From: lwb <q3213421wrwqr>
Date: 星期三, 11 十一月 2020 17:06:33 +0800
Subject: [PATCH] 9527 unity 升级
---
Assets/Plugins/PocoSDK/ConcurrentDictionary.cs | 3098 +++++++++++++++++++++++++++++++----------------------------
1 files changed, 1,627 insertions(+), 1,471 deletions(-)
diff --git a/Assets/Plugins/PocoSDK/ConcurrentDictionary.cs b/Assets/Plugins/PocoSDK/ConcurrentDictionary.cs
index 600bd9b..508ec95 100644
--- a/Assets/Plugins/PocoSDK/ConcurrentDictionary.cs
+++ b/Assets/Plugins/PocoSDK/ConcurrentDictionary.cs
@@ -11,1669 +11,1825 @@
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)]
+ /// <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
+ {
+ [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 KeyValuePair<TKey, TValue>[] m_serializationArray;
+ // Used for custom serialization
- private int m_serializationConcurrencyLevel;
- // used to save the concurrency level in serialization
+ private int m_serializationConcurrencyLevel;
+ // used to save the concurrency level in serialization
- private int m_serializationCapacity;
- // used to save the capacity 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 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;
+ // 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 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 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 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 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 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");
+ /// <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);
- }
+ 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");
+ 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"));
- }
- }
- }
+ 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");
+ /// <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;
- }
+ // 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_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;
- }
+ 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>
+ /// 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");
+ /// <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);
- }
+ 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");
+ /// <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));
- }
+ 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;
+ /// <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);
+ 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;
- }
+ 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);
+ 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 (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;
- }
+ 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 = curr.m_value;
+ m_countPerLock[lockNo]--;
+ return true;
+ }
+ prev = curr;
+ }
+ }
- value = default(TValue);
- return false;
- }
- }
+ 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");
+ /// <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;
+ 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 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];
+ // 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鈥檛 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;
- }
+ // The memory barrier ensures that the load of the fields of 'n' doesn鈥檛 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;
- }
+ value = default(TValue);
+ return false;
+ }
- /// <summary>
- /// Compares the existing value for the specified key with a specified value, and if they鈥檙e 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");
+ /// <summary>
+ /// Compares the existing value for the specified key with a specified value, and if they鈥檙e 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;
+ int hashcode = m_comparer.GetHashCode(key);
+ IEqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default;
- while (true) {
- int bucketNo;
- int lockNo;
+ while (true)
+ {
+ int bucketNo;
+ int lockNo;
- Node[] buckets = m_buckets;
- GetBucketAndLockNo (hashcode, out bucketNo, out lockNo, buckets.Length);
+ 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;
- }
+ 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);
+ // 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;
- }
+ if (prev == null)
+ {
+ buckets[bucketNo] = newNode;
+ }
+ else
+ {
+ prev.m_next = newNode;
+ }
- return true;
- }
+ return true;
+ }
- return false;
- }
+ return false;
+ }
- prev = node;
- }
+ prev = node;
+ }
- //didn't find the key
- return false;
- }
- }
- }
+ //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);
+ /// <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);
- }
- }
+ 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"));
+ /// <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 locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
- int count = 0;
+ int count = 0;
- for (int i = 0; i < m_locks.Length; i++) {
- count += m_countPerLock [i];
- }
+ 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"));
- }
+ 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);
- }
- }
+ 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];
- }
- }
+ /// <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];
+ KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[count];
- CopyToPairs (array, 0);
- return array;
- } finally {
- ReleaseLocks (0, locksAcquired);
- }
- }
+ 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 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 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>
+ /// 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;
+ /// <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];
+ 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鈥檛 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;
- }
- }
- }
+ // The memory barrier ensures that the load of the fields of 'current' doesn鈥檛 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);
+ /// <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;
+ while (true)
+ {
+ int bucketNo, lockNo;
- Node[] buckets = m_buckets;
- GetBucketAndLockNo (hashcode, out bucketNo, out lockNo, buckets.Length);
+ 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;
- }
+ 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;
- }
+ // 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;
- }
+ // 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]++;
- }
+ // 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]);
- }
+ //
+ // 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);
- }
+ //
+ // 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;
- }
- }
+ 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 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;
+ /// <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);
+ 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];
- }
+ // 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);
- }
+ }
+ finally
+ {
+ // Release locks that have been acquired earlier
+ ReleaseLocks(0, acquiredLocks);
+ }
- return count;
- }
- }
+ 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");
+ /// <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;
- }
+ 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");
+ /// <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;
- }
+ 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");
+ /// <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;
- }
- }
- }
- }
+ 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>
+ /// 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);
+ /// <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);
- }
+ 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;
- }
- }
+ return true;
+ }
+ }
- #region IDictionary<TKey,TValue> members
+ #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>
+ /// 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>
+ /// 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 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 (); }
- }
+ /// <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
+ #endregion
- #region ICollection<KeyValuePair<TKey,TValue>> Members
+ #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>
+ /// 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>
+ /// 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>
+ /// 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"));
+ /// <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);
- }
+ TValue throwAwayValue;
+ return TryRemoveInternal(keyValuePair.Key, out throwAwayValue, true, keyValuePair.Value);
+ }
- #endregion
+ #endregion
- #region IEnumerable Members
+ #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 ();
- }
+ /// <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
+ #endregion
- #region IDictionary Members
+ #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"));
+ /// <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"));
- }
+ TValue typedValue;
+ try
+ {
+ typedValue = (TValue)value;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect"));
+ }
- ((IDictionary<TKey, TValue>)this).Add ((TKey)key, typedValue);
- }
+ ((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");
+ /// <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);
- }
+ 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>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}"/> 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 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>
+ /// 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");
+ /// <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);
- }
- }
+ 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 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");
+ /// <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;
- }
+ TValue value;
+ if (key is TKey && this.TryGetValue((TKey)key, out value))
+ {
+ return value;
+ }
- return null;
- }
- set {
- if (key == null)
- throw new ArgumentNullException ("key");
+ 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"));
+ 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;
- }
- }
+ ((ConcurrentDictionary<TKey, TValue>)this)[(TKey)key] = (TValue)value;
+ }
+ }
- #endregion
+ #endregion
- #region ICollection Members
+ #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"));
+ /// <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 locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
- int count = 0;
+ int count = 0;
- for (int i = 0; i < m_locks.Length; i++) {
- count += m_countPerLock [i];
- }
+ 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"));
- }
+ 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
+ // 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;
- }
+ 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;
- }
+ DictionaryEntry[] entries = array as DictionaryEntry[];
+ if (entries != null)
+ {
+ CopyToEntries(entries, index);
+ return;
+ }
- object[] objects = array as object[];
- if (objects != null) {
- CopyToObjects (objects, 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);
- }
- }
+ 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 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 ();
- }
- }
+ /// <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
+ #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);
+ /// <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;
- }
+ // 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;
+ // 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;
- }
+ // 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;
- }
+ 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];
+ 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);
+ // 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);
+ // 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]);
+ newBuckets[newBucketNo] = new Node(current.m_key, current.m_value, current.m_hashcode, newBuckets[newBucketNo]);
- checked {
- newCountPerLock [newLockNo]++;
- }
+ checked
+ {
+ newCountPerLock[newLockNo]++;
+ }
- current = next;
- }
- }
+ current = next;
+ }
+ }
- // And finally adjust m_buckets and m_countPerLock to point to data for the new table
- m_buckets = newBuckets;
- m_countPerLock = newCountPerLock;
+ // 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);
- }
- }
+ }
+ 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;
+ /// <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);
- }
+ 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 {
+ /// <summary>
+ /// The number of concurrent writes for which to optimize by default.
+ /// </summary>
+ private static int DefaultConcurrencyLevel
+ {
- get { return DEFAULT_CONCURRENCY_MULTIPLIER * Environment.ProcessorCount; }
- }
+ 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 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);
+ /// <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++;
- }
- }
- }
- }
+ 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);
+ /// <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]);
- }
- }
+ 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> ();
+ /// <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;
- }
- }
+ 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);
- }
- }
+ 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> ();
+ /// <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;
- }
- }
+ 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);
- }
- }
+ 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 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);
+ /// <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;
- }
+ 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;
+ /// <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)
+ : 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;
- }
- }
+ 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.
+ /// <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 ();
- }
+ 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 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 Key
+ {
+ get { return m_enumerator.Current.Key; }
+ }
- public object Value {
- get { return m_enumerator.Current.Value; }
- }
+ public object Value
+ {
+ get { return m_enumerator.Current.Value; }
+ }
- public object Current {
- get { return this.Entry; }
- }
+ public object Current
+ {
+ get { return this.Entry; }
+ }
- public bool MoveNext ()
- {
- return m_enumerator.MoveNext ();
- }
+ public bool MoveNext()
+ {
+ return m_enumerator.MoveNext();
+ }
- public void Reset ()
- {
- m_enumerator.Reset ();
- }
- }
+ 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>
+ /// 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;
+ /// <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_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 ();
- }
+ 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;
+ InitializeFromCollection(array);
+ m_serializationArray = null;
- }
- }
+ }
+ }
}
#endif
\ No newline at end of file
--
Gitblit v1.8.0