少年修仙传客户端基础资源
lwb
2020-11-11 ba24a4a15c0317ac2fd954f4173b4b79cbdf191e
Assets/Plugins/PocoSDK/ConcurrentDictionary.cs
@@ -177,11 +177,13 @@
      private void InitializeFromCollection (IEnumerable<KeyValuePair<TKey, TValue>> collection)
      {
         TValue dummy;
         foreach (KeyValuePair<TKey, TValue> pair in collection) {
            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)) {
                if (!TryAddInternal(pair.Key, pair.Value, false, false, out dummy))
                {
               throw new ArgumentException (GetResource ("ConcurrentDictionary_SourceContainsDuplicateKeys"));
            }
         }
@@ -207,10 +209,12 @@
      /// (Nothing in Visual Basic).</exception>
      public ConcurrentDictionary (int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer)
      {
         if (concurrencyLevel < 1) {
            if (concurrencyLevel < 1)
            {
            throw new ArgumentOutOfRangeException ("concurrencyLevel", GetResource ("ConcurrentDictionary_ConcurrencyLevelMustBePositive"));
         }
         if (capacity < 0) {
            if (capacity < 0)
            {
            throw new ArgumentOutOfRangeException ("capacity", GetResource ("ConcurrentDictionary_CapacityMustNotBeNegative"));
         }
         if (comparer == null)
@@ -218,12 +222,14 @@
         // 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) {
            if (capacity < concurrencyLevel)
            {
            capacity = concurrencyLevel;
         }
         m_locks = new object[concurrencyLevel];
         for (int i = 0; i < m_locks.Length; i++) {
            for (int i = 0; i < m_locks.Length; i++)
            {
            m_locks [i] = new object ();
         }
@@ -306,35 +312,45 @@
      /// <returns></returns>
      private bool TryRemoveInternal (TKey key, out TValue value, bool matchValue, TValue oldValue)
      {
         while (true) {
            while (true)
            {
            Node[] buckets = m_buckets;
            int bucketNo, lockNo;
            GetBucketAndLockNo (m_comparer.GetHashCode (key), out bucketNo, out lockNo, buckets.Length);
            lock (m_locks[lockNo]) {
                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) {
                    if (buckets != m_buckets)
                    {
                  continue;
               }
               Node prev = null;
               for (Node curr = m_buckets [bucketNo]; curr != null; curr = curr.m_next) {
                    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) {
                        if (m_comparer.Equals(curr.m_key, key))
                        {
                            if (matchValue)
                            {
                        bool valuesMatch = EqualityComparer<TValue>.Default.Equals (oldValue, curr.m_value);
                        if (!valuesMatch) {
                                if (!valuesMatch)
                                {
                           value = default(TValue);
                           return false;
                        }
                     }
                     if (prev == null) {
                            if (prev == null)
                            {
                        m_buckets [bucketNo] = curr.m_next;
                     } else {
                            }
                            else
                            {
                        prev.m_next = curr.m_next;
                     }
@@ -380,8 +396,10 @@
         // The memory barrier ensures that the load of the fields of 'n' doesn’t move before the load from buckets[i]. 
         Thread.MemoryBarrier ();
         while (n != null) {
            if (m_comparer.Equals (n.m_key, key)) {
            while (n != null)
            {
                if (m_comparer.Equals(n.m_key, key))
                {
               value = n.m_value;
               return true;
            }
@@ -415,34 +433,43 @@
         int hashcode = m_comparer.GetHashCode (key);
         IEqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default;
         while (true) {
            while (true)
            {
            int bucketNo;
            int lockNo;
            Node[] buckets = m_buckets;
            GetBucketAndLockNo (hashcode, out bucketNo, out lockNo, buckets.Length);
            lock (m_locks[lockNo]) {
                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) {
                    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) {
                    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)) {
                        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) {
                                if (prev == null)
                                {
                           buckets [bucketNo] = newNode;
                        } else {
                                }
                                else
                                {
                           prev.m_next = newNode;
                        }
@@ -467,12 +494,15 @@
      public void Clear ()
      {
         int locksAcquired = 0;
         try {
            try
            {
            AcquireAllLocks (ref locksAcquired);
            m_buckets = new Node[DEFAULT_CAPACITY];
            Array.Clear (m_countPerLock, 0, m_countPerLock.Length);
         } finally {
            }
            finally
            {
            ReleaseLocks (0, locksAcquired);
         }
      }
@@ -506,21 +536,26 @@
            throw new ArgumentOutOfRangeException ("index", GetResource ("ConcurrentDictionary_IndexIsNegative"));
         int locksAcquired = 0;
         try {
            try
            {
            AcquireAllLocks (ref locksAcquired);
            int count = 0;
            for (int i = 0; i < m_locks.Length; 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
                if (array.Length - count < index || count < 0)
                { //"count" itself or "count + index" can overflow
               throw new ArgumentException (GetResource ("ConcurrentDictionary_ArrayNotLargeEnough"));
            }
            CopyToPairs (array, index);
         } finally {
            }
            finally
            {
            ReleaseLocks (0, locksAcquired);
         }
      }
@@ -534,11 +569,14 @@
      public KeyValuePair<TKey, TValue>[] ToArray ()
      {
         int locksAcquired = 0;
         try {
            try
            {
            AcquireAllLocks (ref locksAcquired);
            int count = 0;
            checked {
               for (int i = 0; i < m_locks.Length; i++) {
                checked
                {
                    for (int i = 0; i < m_locks.Length; i++)
                    {
                  count += m_countPerLock [i];
               }
            }
@@ -547,7 +585,9 @@
            CopyToPairs (array, 0);
            return array;
         } finally {
            }
            finally
            {
            ReleaseLocks (0, locksAcquired);
         }
      }
@@ -560,8 +600,10 @@
      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) {
            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
            }
@@ -576,8 +618,10 @@
      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) {
            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
            }
@@ -592,8 +636,10 @@
      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) {
            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
            }
@@ -613,12 +659,14 @@
      {
         Node[] buckets = m_buckets;
         for (int i = 0; i < buckets.Length; 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’t move before the load from buckets[i]. 
            Thread.MemoryBarrier ();
            while (current != null) {
                while (current != null)
                {
               yield return new KeyValuePair<TKey, TValue> (current.m_key, current.m_value);
               current = current.m_next;
            }
@@ -634,7 +682,8 @@
      {
         int hashcode = m_comparer.GetHashCode (key);
         while (true) {
            while (true)
            {
            int bucketNo, lockNo;
            Node[] buckets = m_buckets;
@@ -642,35 +691,46 @@
            bool resizeDesired = false;
            bool lockTaken = false;
            try {
               if (acquireLock) {
                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) {
                    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) {
                    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 (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) {
                            if (updateIfExists)
                            {
                        Node newNode = new Node (node.m_key, value, hashcode, node.m_next);
                        if (prev == null) {
                                if (prev == null)
                                {
                           buckets [bucketNo] = newNode;
                        } else {
                                }
                                else
                                {
                           prev.m_next = newNode;
                        }
                        resultingValue = value;
                     } else {
                            }
                            else
                            {
                        resultingValue = node.m_value;
                     }
                     return false;
@@ -680,7 +740,8 @@
               // The key was not found in the bucket. Insert the key-value pair. 
               buckets [bucketNo] = new Node (key, value, hashcode, buckets [bucketNo]);
               checked {
                    checked
                    {
                  m_countPerLock [lockNo]++;
               }
@@ -689,10 +750,13 @@
               // 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) {
                    if (m_countPerLock[lockNo] > buckets.Length / m_locks.Length)
                    {
                  resizeDesired = true;
               }
            } finally {
                }
                finally
                {
               if (lockTaken)
                  Monitor.Exit (m_locks [lockNo]);
            }
@@ -705,7 +769,8 @@
            // - 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) {
                if (resizeDesired)
                {
               GrowTable (buckets);
            }
@@ -727,15 +792,19 @@
      /// <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 {
        public TValue this[TKey key]
        {
            get
            {
            TValue value;
            if (!TryGetValue (key, out value)) {
                if (!TryGetValue(key, out value))
                {
               throw new KeyNotFoundException ();
            }
            return value;
         }
         set {
            set
            {
            if (key == null)
               throw new ArgumentNullException ("key");
            TValue dummy;
@@ -754,21 +823,27 @@
      /// <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 {
        public int Count
        {
            get
            {
            int count = 0;
            int acquiredLocks = 0;
            try {
                try
                {
               // Acquire all locks
               AcquireAllLocks (ref acquiredLocks);
               // Compute the count, we allow overflow 
               for (int i = 0; i < m_countPerLock.Length; i++) {
                    for (int i = 0; i < m_countPerLock.Length; i++)
                    {
                  count += m_countPerLock [i];
               }
            } finally {
                }
                finally
                {
               // Release locks that have been acquired earlier 
               ReleaseLocks (0, acquiredLocks);
            }
@@ -800,7 +875,8 @@
            throw new ArgumentNullException ("valueFactory");
         TValue resultingValue;
         if (TryGetValue (key, out resultingValue)) {
            if (TryGetValue(key, out resultingValue))
            {
            return resultingValue;
         }
         TryAddInternal (key, valueFactory (key), false, true, out resultingValue);
@@ -858,17 +934,22 @@
            throw new ArgumentNullException ("updateValueFactory");
         TValue newValue, resultingValue;
         while (true) {
            while (true)
            {
            TValue oldValue;
            if (TryGetValue (key, out oldValue))
 {                //key exists, try to update 
               newValue = updateValueFactory (key, oldValue);
               if (TryUpdate (key, newValue, oldValue)) {
                    if (TryUpdate(key, newValue, oldValue))
                    {
                  return newValue;
               }
            } else { //try add
                }
                else
                { //try add
               newValue = addValueFactory (key);
               if (TryAddInternal (key, newValue, false, true, out resultingValue)) {
                    if (TryAddInternal(key, newValue, false, true, out resultingValue))
                    {
                  return resultingValue;
               }
            }
@@ -899,16 +980,21 @@
         if (updateValueFactory == null)
            throw new ArgumentNullException ("updateValueFactory");
         TValue newValue, resultingValue;
         while (true) {
            while (true)
            {
            TValue oldValue;
            if (TryGetValue (key, out oldValue))
 {                //key exists, try to update 
               newValue = updateValueFactory (key, oldValue);
               if (TryUpdate (key, newValue, oldValue)) {
                    if (TryUpdate(key, newValue, oldValue))
                    {
                  return newValue;
               }
            } else { //try add
               if (TryAddInternal (key, addValue, false, true, out resultingValue)) {
                }
                else
                { //try add
                    if (TryAddInternal(key, addValue, false, true, out resultingValue))
                    {
                  return resultingValue;
               }
            }
@@ -922,19 +1008,26 @@
      /// </summary>
      /// <value>true if the <see cref="ConcurrentDictionary{TKey,TValue}"/> is empty; otherwise, 
      /// false.</value>
      public bool IsEmpty {
         get {
        public bool IsEmpty
        {
            get
            {
            int acquiredLocks = 0;
            try {
                try
                {
               // Acquire all locks 
               AcquireAllLocks (ref acquiredLocks);
               for (int i = 0; i < m_countPerLock.Length; i++) {
                  if (m_countPerLock [i] != 0) {
                    for (int i = 0; i < m_countPerLock.Length; i++)
                    {
                        if (m_countPerLock[i] != 0)
                        {
                     return false;
                  }
               }
            } finally {
                }
                finally
                {
               // Release locks that have been acquired earlier 
               ReleaseLocks (0, acquiredLocks);
            }
@@ -960,7 +1053,8 @@
      /// cref="ConcurrentDictionary{TKey,TValue}"/>.</exception>
      void IDictionary<TKey, TValue>.Add (TKey key, TValue value)
      {
         if (!TryAdd (key, value)) {
            if (!TryAdd(key, value))
            {
            throw new ArgumentException (GetResource ("ConcurrentDictionary_KeyAlreadyExisted"));
         }
      }
@@ -989,7 +1083,8 @@
      /// </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 {
        public ICollection<TKey> Keys
        {
         get { return GetKeys (); }
      }
@@ -1000,7 +1095,8 @@
      /// <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 {
        public ICollection<TValue> Values
        {
         get { return GetValues (); }
      }
@@ -1039,7 +1135,8 @@
      bool ICollection<KeyValuePair<TKey, TValue>>.Contains (KeyValuePair<TKey, TValue> keyValuePair)
      {
         TValue value;
         if (!TryGetValue (keyValuePair.Key, out value)) {
            if (!TryGetValue(keyValuePair.Key, out value))
            {
            return false;
         }
         return EqualityComparer<TValue>.Default.Equals (value, keyValuePair.Value);
@@ -1052,7 +1149,8 @@
      /// 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 {
        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
        {
         get { return false; }
      }
@@ -1123,9 +1221,12 @@
            throw new ArgumentException (GetResource ("ConcurrentDictionary_TypeOfKeyIncorrect"));
         TValue typedValue;
         try {
            try
            {
            typedValue = (TValue)value;
         } catch (InvalidCastException) {
            }
            catch (InvalidCastException)
            {
            throw new ArgumentException (GetResource ("ConcurrentDictionary_TypeOfValueIncorrect"));
         }
@@ -1167,7 +1268,8 @@
      /// fixed size; otherwise, false. For <see
      /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>, this property always
      /// returns false.</value> 
      bool IDictionary.IsFixedSize {
        bool IDictionary.IsFixedSize
        {
         get { return false; }
      }
@@ -1179,7 +1281,8 @@
      /// read-only; otherwise, false. For <see 
      /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>, this property always 
      /// returns false.</value>
      bool IDictionary.IsReadOnly {
        bool IDictionary.IsReadOnly
        {
         get { return false; }
      }
@@ -1189,7 +1292,8 @@
      /// </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 {
        ICollection IDictionary.Keys
        {
         get { return GetKeys (); }
      }
@@ -1206,7 +1310,8 @@
            throw new ArgumentNullException ("key");
         TValue throwAwayValue;
         if (key is TKey) {
            if (key is TKey)
            {
            this.TryRemove ((TKey)key, out throwAwayValue);
         }
      }
@@ -1217,7 +1322,8 @@
      /// </summary>
      /// <value>An <see cref="T:System.Collections.ICollection"/> containing the values in the <see
      /// cref="T:System.Collections.IDictionary"/>.</value>
      ICollection IDictionary.Values {
        ICollection IDictionary.Values
        {
         get { return GetValues (); }
      }
@@ -1239,19 +1345,23 @@
      /// <typeparamref name="TValue"/> of the <see 
      /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/> 
      /// </exception>
      object IDictionary.this [object key] {
         get {
        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)) {
                if (key is TKey && this.TryGetValue((TKey)key, out value))
                {
               return value;
            }
            return null;
         }
         set {
            set
            {
            if (key == null)
               throw new ArgumentNullException ("key");
@@ -1294,16 +1404,19 @@
            throw new ArgumentOutOfRangeException ("index", GetResource ("ConcurrentDictionary_IndexIsNegative"));
         int locksAcquired = 0;
         try {
            try
            {
            AcquireAllLocks (ref locksAcquired);
            int count = 0;
            for (int i = 0; i < m_locks.Length; 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
                if (array.Length - count < index || count < 0)
                { //"count" itself or "count + index" can overflow
               throw new ArgumentException (GetResource ("ConcurrentDictionary_ArrayNotLargeEnough"));
            }
@@ -1314,25 +1427,30 @@
            //    - an array of objects
            KeyValuePair<TKey, TValue>[] pairs = array as KeyValuePair<TKey, TValue>[];
            if (pairs != null) {
                if (pairs != null)
                {
               CopyToPairs (pairs, index);
               return;
            }
            DictionaryEntry[] entries = array as DictionaryEntry[];
            if (entries != null) {
                if (entries != null)
                {
               CopyToEntries (entries, index);
               return;
            }
            object[] objects = array as object[];
            if (objects != null) {
                if (objects != null)
                {
               CopyToObjects (objects, index);
               return;
            }
            throw new ArgumentException (GetResource ("ConcurrentDictionary_ArrayIncorrectType"), "array");
         } finally {
            }
            finally
            {
            ReleaseLocks (0, locksAcquired);
         }
      }
@@ -1345,7 +1463,8 @@
      /// (thread safe); otherwise, false. For <see
      /// cref="T:System.Collections.Concurrent.ConcurrentDictionary{TKey,TValue}"/>, this property always
      /// returns false.</value>
      bool ICollection.IsSynchronized {
        bool ICollection.IsSynchronized
        {
         get { return false; }
      }
@@ -1354,8 +1473,10 @@
      /// 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 {
        object ICollection.SyncRoot
        {
            get
            {
            throw new NotSupportedException ();
         }
      }
@@ -1372,12 +1493,14 @@
      private void GrowTable (Node[] buckets)
      {
         int locksAcquired = 0;
         try {
            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) {
                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.
@@ -1387,20 +1510,25 @@
            // 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 {
                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) {
                        while (newLength % 3 == 0 || newLength % 5 == 0 || newLength % 7 == 0)
                        {
                     newLength += 2;
                  }
                  Assert (newLength % 2 != 0);
               }
            } catch (OverflowException) {
                }
                catch (OverflowException)
                {
               // If we were to resize the table, its new size will not fit into a 32-bit signed int. Just return. 
               return;
            }
@@ -1412,16 +1540,19 @@
            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++) {
                for (int i = 0; i < buckets.Length; i++)
                {
               Node current = buckets [i];
               while (current != null) {
                    while (current != null)
                    {
                  Node next = current.m_next;
                  int newBucketNo, newLockNo;
                  GetBucketAndLockNo (current.m_hashcode, out newBucketNo, out newLockNo, newBuckets.Length);
                  newBuckets [newBucketNo] = new Node (current.m_key, current.m_value, current.m_hashcode, newBuckets [newBucketNo]);
                  checked {
                        checked
                        {
                     newCountPerLock [newLockNo]++;
                  }
@@ -1433,7 +1564,9 @@
            m_buckets = newBuckets;
            m_countPerLock = newCountPerLock;
         } finally {
            }
            finally
            {
            // Release all locks that we took earlier 
            ReleaseLocks (0, locksAcquired);
         }
@@ -1455,7 +1588,8 @@
      /// <summary> 
      /// The number of concurrent writes for which to optimize by default.
      /// </summary>
      private static int DefaultConcurrencyLevel {
        private static int DefaultConcurrencyLevel
        {
         get { return DEFAULT_CONCURRENCY_MULTIPLIER * Environment.ProcessorCount; }
      }
@@ -1480,13 +1614,18 @@
      {
         Assert (fromInclusive <= toExclusive);
         for (int i = fromInclusive; i < toExclusive; i++) {
            for (int i = fromInclusive; i < toExclusive; i++)
            {
            bool lockTaken = false;
            try {
                try
                {
               Monitor.Enter (m_locks [i]);
               lockTaken = true;
            } finally {
               if (lockTaken) {
                }
                finally
                {
                    if (lockTaken)
                    {
                  locksAcquired++;
               }
            }
@@ -1500,7 +1639,8 @@
      {
         Assert (fromInclusive <= toExclusive);
         for (int i = fromInclusive; i < toExclusive; i++) {
            for (int i = fromInclusive; i < toExclusive; i++)
            {
            Monitor.Exit (m_locks [i]);
         }
      }
@@ -1511,20 +1651,25 @@
      private ReadOnlyCollection<TKey> GetKeys ()
      {
         int locksAcquired = 0;
         try {
            try
            {
            AcquireAllLocks (ref locksAcquired);
            List<TKey> keys = new List<TKey> ();
            for (int i = 0; i < m_buckets.Length; i++) {
                for (int i = 0; i < m_buckets.Length; i++)
                {
               Node current = m_buckets [i];
               while (current != null) {
                    while (current != null)
                    {
                  keys.Add (current.m_key);
                  current = current.m_next;
               }
            }
            return new ReadOnlyCollection<TKey> (keys);
         } finally {
            }
            finally
            {
            ReleaseLocks (0, locksAcquired);
         }
      }
@@ -1535,20 +1680,25 @@
      private ReadOnlyCollection<TValue> GetValues ()
      {
         int locksAcquired = 0;
         try {
            try
            {
            AcquireAllLocks (ref locksAcquired);
            List<TValue> values = new List<TValue> ();
            for (int i = 0; i < m_buckets.Length; i++) {
                for (int i = 0; i < m_buckets.Length; i++)
                {
               Node current = m_buckets [i];
               while (current != null) {
                    while (current != null)
                    {
                  values.Add (current.m_value);
                  current = current.m_next;
               }
            }
            return new ReadOnlyCollection<TValue> (values);
         } finally {
            }
            finally
            {
            ReleaseLocks (0, locksAcquired);
         }
      }
@@ -1559,7 +1709,8 @@
      [Conditional ("DEBUG")]
      private void Assert (bool condition)
      {
         if (!condition) {
            if (!condition)
            {
            throw new Exception ("Assertion failed.");
         }
      }
@@ -1614,19 +1765,23 @@
            m_enumerator = dictionary.GetEnumerator ();
         }
         public DictionaryEntry Entry {
            public DictionaryEntry Entry
            {
            get { return new DictionaryEntry (m_enumerator.Current.Key, m_enumerator.Current.Value); }
         }
         public object Key {
            public object Key
            {
            get { return m_enumerator.Current.Key; }
         }
         public object Value {
            public object Value
            {
            get { return m_enumerator.Current.Value; }
         }
         public object Current {
            public object Current
            {
            get { return this.Entry; }
         }
@@ -1665,7 +1820,8 @@
         m_countPerLock = new int[m_serializationConcurrencyLevel];
         m_locks = new object[m_serializationConcurrencyLevel];
         for (int i = 0; i < m_locks.Length; i++) {
            for (int i = 0; i < m_locks.Length; i++)
            {
            m_locks [i] = new object ();
         }