Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ConcurrentDictionary.cs
Go to the documentation of this file.
7
9
11[DebuggerDisplay("Count = {Count}")]
12public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>> where TKey : notnull
13{
14 private sealed class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IDisposable, IEnumerator
15 {
17
18 private Node[] _buckets;
19
20 private Node _node;
21
22 private int _i;
23
24 private int _state;
25
26 public KeyValuePair<TKey, TValue> Current { get; private set; }
27
28 object IEnumerator.Current => Current;
29
35
36 public void Reset()
37 {
38 _buckets = null;
39 _node = null;
41 _i = -1;
42 _state = 0;
43 }
44
45 public void Dispose()
46 {
47 }
48
49 public bool MoveNext()
50 {
51 switch (_state)
52 {
53 case 0:
55 _i = -1;
56 goto case 1;
57 case 1:
58 {
59 Node[] buckets = _buckets;
60 int num = ++_i;
61 if ((uint)num >= (uint)buckets.Length)
62 {
63 break;
64 }
65 _node = Volatile.Read(ref buckets[num]);
66 _state = 2;
67 goto case 2;
68 }
69 case 2:
70 {
71 Node node = _node;
72 if (node != null)
73 {
74 Current = new KeyValuePair<TKey, TValue>(node._key, node._value);
75 _node = node._next;
76 return true;
77 }
78 goto case 1;
79 }
80 }
81 _state = 3;
82 return false;
83 }
84 }
85
86 private sealed class Node
87 {
88 internal readonly TKey _key;
89
90 internal TValue _value;
91
92 internal volatile Node _next;
93
94 internal readonly int _hashcode;
95
96 internal Node(TKey key, TValue value, int hashcode, Node next)
97 {
98 _key = key;
99 _value = value;
100 _next = next;
102 }
103 }
104
105 private sealed class Tables
106 {
107 internal readonly Node[] _buckets;
108
109 internal readonly object[] _locks;
110
111 internal readonly int[] _countPerLock;
112
113 internal readonly ulong _fastModBucketsMultiplier;
114
115 internal Tables(Node[] buckets, object[] locks, int[] countPerLock)
116 {
117 _buckets = buckets;
118 _locks = locks;
120 _ = IntPtr.Size;
122 }
123
124 [MethodImpl(MethodImplOptions.AggressiveInlining)]
126 {
127 Node[] buckets = _buckets;
128 if (IntPtr.Size == 8)
129 {
130 return ref buckets[System.Collections.HashHelpers.FastMod((uint)hashcode, (uint)buckets.Length, _fastModBucketsMultiplier)];
131 }
132 return ref buckets[(uint)hashcode % (uint)buckets.Length];
133 }
134
135 [MethodImpl(MethodImplOptions.AggressiveInlining)]
137 {
138 Node[] buckets = _buckets;
139 uint num = ((IntPtr.Size != 8) ? ((uint)hashcode % (uint)buckets.Length) : System.Collections.HashHelpers.FastMod((uint)hashcode, (uint)buckets.Length, _fastModBucketsMultiplier));
140 lockNo = num % (uint)_locks.Length;
141 return ref buckets[num];
142 }
143 }
144
146 {
148
150
151 public object Key => _enumerator.Current.Key;
152
153 public object Value => _enumerator.Current.Value;
154
155 public object Current => Entry;
156
161
162 public bool MoveNext()
163 {
164 return _enumerator.MoveNext();
165 }
166
167 public void Reset()
168 {
170 }
171 }
172
173 private volatile Tables _tables;
174
176
178
179 private readonly bool _growLockArray;
180
181 private int _budget;
182
183 private static readonly bool s_isValueWriteAtomic = IsValueWriteAtomic();
184
185 public TValue this[TKey key]
186 {
187 get
188 {
189 if (!TryGetValue(key, out var value))
190 {
192 }
193 return value;
194 }
195 set
196 {
197 if (key == null)
198 {
200 }
201 TryAddInternal(key, null, value, updateIfExists: true, acquireLock: true, out var _);
202 }
203 }
204
206
207 public int Count
208 {
209 get
210 {
211 int locksAcquired = 0;
212 try
213 {
215 return GetCountInternal();
216 }
217 finally
218 {
220 }
221 }
222 }
223
224 public bool IsEmpty
225 {
226 get
227 {
228 if (!AreAllBucketsEmpty())
229 {
230 return false;
231 }
232 int locksAcquired = 0;
233 try
234 {
236 return AreAllBucketsEmpty();
237 }
238 finally
239 {
241 }
242 }
243 }
244
246
248
250
252
254
255 bool IDictionary.IsFixedSize => false;
256
257 bool IDictionary.IsReadOnly => false;
258
259 ICollection IDictionary.Keys => GetKeys();
260
261 ICollection IDictionary.Values => GetValues();
262
263 object? IDictionary.this[object key]
264 {
265 get
266 {
267 if (key == null)
268 {
270 }
271 if (key is TKey key2 && TryGetValue(key2, out var value))
272 {
273 return value;
274 }
275 return null;
276 }
277 set
278 {
279 if (key == null)
280 {
282 }
283 if (!(key is TKey))
284 {
286 }
288 this[(TKey)key] = (TValue)value;
289 }
290 }
291
292 bool ICollection.IsSynchronized => false;
293
294 object ICollection.SyncRoot
295 {
296 get
297 {
299 }
300 }
301
303
304 private static bool IsValueWriteAtomic()
305 {
306 if (!typeof(TValue).IsValueType || typeof(TValue) == typeof(IntPtr) || typeof(TValue) == typeof(UIntPtr))
307 {
308 return true;
309 }
310 switch (Type.GetTypeCode(typeof(TValue)))
311 {
312 case TypeCode.Boolean:
313 case TypeCode.Char:
314 case TypeCode.SByte:
315 case TypeCode.Byte:
316 case TypeCode.Int16:
317 case TypeCode.UInt16:
318 case TypeCode.Int32:
319 case TypeCode.UInt32:
320 case TypeCode.Single:
321 return true;
322 case TypeCode.Int64:
323 case TypeCode.UInt64:
324 case TypeCode.Double:
325 return IntPtr.Size == 8;
326 default:
327 return false;
328 }
329 }
330
335
340
345
350
360
370
372 {
374 {
375 if (item.Key == null)
376 {
378 }
379 if (!TryAddInternal(item.Key, null, item.Value, updateIfExists: false, acquireLock: false, out var _))
380 {
382 }
383 }
384 if (_budget == 0)
385 {
387 _budget = tables._buckets.Length / tables._locks.Length;
388 }
389 }
390
395
397 {
398 if (concurrencyLevel < 1)
399 {
401 }
402 if (capacity < 0)
403 {
405 }
407 {
409 }
410 object[] array = new object[concurrencyLevel];
411 array[0] = array;
412 for (int i = 1; i < array.Length; i++)
413 {
414 array[i] = new object();
415 }
416 int[] countPerLock = new int[array.Length];
417 Node[] array2 = new Node[capacity];
421 {
423 }
425 _budget = array2.Length / array.Length;
426 }
427
428 public bool TryAdd(TKey key, TValue value)
429 {
430 if (key == null)
431 {
433 }
434 TValue resultingValue;
435 return TryAddInternal(key, null, value, updateIfExists: false, acquireLock: true, out resultingValue);
436 }
437
438 public bool ContainsKey(TKey key)
439 {
440 if (key == null)
441 {
443 }
444 TValue value;
445 return TryGetValue(key, out value);
446 }
447
448 public bool TryRemove(TKey key, [MaybeNullWhen(false)] out TValue value)
449 {
450 if (key == null)
451 {
453 }
454 return TryRemoveInternal(key, out value, matchValue: false, default(TValue));
455 }
456
458 {
459 if (item.Key == null)
460 {
462 }
463 TValue value;
464 return TryRemoveInternal(item.Key, out value, matchValue: true, item.Value);
465 }
466
467 private bool TryRemoveInternal(TKey key, [MaybeNullWhen(false)] out TValue value, bool matchValue, TValue oldValue)
468 {
470 int num = comparer?.GetHashCode(key) ?? key.GetHashCode();
471 while (true)
472 {
474 object[] locks = tables._locks;
475 uint lockNo;
476 ref Node bucketAndLock = ref tables.GetBucketAndLock(num, out lockNo);
477 lock (locks[lockNo])
478 {
479 if (tables != _tables)
480 {
481 continue;
482 }
483 Node node = null;
484 for (Node node2 = bucketAndLock; node2 != null; node2 = node2._next)
485 {
486 if (num == node2._hashcode && (comparer?.Equals(node2._key, key) ?? _defaultComparer.Equals(node2._key, key)))
487 {
489 {
490 value = default(TValue);
491 return false;
492 }
493 if (node == null)
494 {
496 }
497 else
498 {
499 node._next = node2._next;
500 }
501 value = node2._value;
502 tables._countPerLock[lockNo]--;
503 return true;
504 }
505 node = node2;
506 }
507 break;
508 }
509 }
510 value = default(TValue);
511 return false;
512 }
513
514 public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
515 {
516 if (key == null)
517 {
519 }
522 if (comparer == null)
523 {
524 int hashCode = key.GetHashCode();
525 if (typeof(TKey).IsValueType)
526 {
527 for (Node node = Volatile.Read(ref tables.GetBucket(hashCode)); node != null; node = node._next)
528 {
529 if (hashCode == node._hashcode && EqualityComparer<TKey>.Default.Equals(node._key, key))
530 {
531 value = node._value;
532 return true;
533 }
534 }
535 }
536 else
537 {
538 for (Node node2 = Volatile.Read(ref tables.GetBucket(hashCode)); node2 != null; node2 = node2._next)
539 {
540 if (hashCode == node2._hashcode && _defaultComparer.Equals(node2._key, key))
541 {
542 value = node2._value;
543 return true;
544 }
545 }
546 }
547 }
548 else
549 {
550 int hashCode2 = comparer.GetHashCode(key);
551 for (Node node3 = Volatile.Read(ref tables.GetBucket(hashCode2)); node3 != null; node3 = node3._next)
552 {
553 if (hashCode2 == node3._hashcode && comparer.Equals(node3._key, key))
554 {
555 value = node3._value;
556 return true;
557 }
558 }
559 }
560 value = default(TValue);
561 return false;
562 }
563
564 private bool TryGetValueInternal(TKey key, int hashcode, [MaybeNullWhen(false)] out TValue value)
565 {
568 if (comparer == null)
569 {
570 if (typeof(TKey).IsValueType)
571 {
572 for (Node node = Volatile.Read(ref tables.GetBucket(hashcode)); node != null; node = node._next)
573 {
574 if (hashcode == node._hashcode && EqualityComparer<TKey>.Default.Equals(node._key, key))
575 {
576 value = node._value;
577 return true;
578 }
579 }
580 }
581 else
582 {
583 for (Node node2 = Volatile.Read(ref tables.GetBucket(hashcode)); node2 != null; node2 = node2._next)
584 {
585 if (hashcode == node2._hashcode && _defaultComparer.Equals(node2._key, key))
586 {
587 value = node2._value;
588 return true;
589 }
590 }
591 }
592 }
593 else
594 {
595 for (Node node3 = Volatile.Read(ref tables.GetBucket(hashcode)); node3 != null; node3 = node3._next)
596 {
597 if (hashcode == node3._hashcode && comparer.Equals(node3._key, key))
598 {
599 value = node3._value;
600 return true;
601 }
602 }
603 }
604 value = default(TValue);
605 return false;
606 }
607
608 public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
609 {
610 if (key == null)
611 {
613 }
615 }
616
617 private bool TryUpdateInternal(TKey key, int? nullableHashcode, TValue newValue, TValue comparisonValue)
618 {
620 int num = nullableHashcode ?? comparer?.GetHashCode(key) ?? key.GetHashCode();
622 while (true)
623 {
625 object[] locks = tables._locks;
626 uint lockNo;
627 ref Node bucketAndLock = ref tables.GetBucketAndLock(num, out lockNo);
628 lock (locks[lockNo])
629 {
630 if (tables != _tables)
631 {
632 continue;
633 }
634 Node node = null;
635 for (Node node2 = bucketAndLock; node2 != null; node2 = node2._next)
636 {
637 if (num == node2._hashcode && (comparer?.Equals(node2._key, key) ?? _defaultComparer.Equals(node2._key, key)))
638 {
639 if (@default.Equals(node2._value, comparisonValue))
640 {
642 {
643 node2._value = newValue;
644 }
645 else
646 {
647 Node node3 = new Node(node2._key, newValue, num, node2._next);
648 if (node == null)
649 {
651 }
652 else
653 {
654 node._next = node3;
655 }
656 }
657 return true;
658 }
659 return false;
660 }
661 node = node2;
662 }
663 return false;
664 }
665 }
666 }
667
668 public void Clear()
669 {
670 int locksAcquired = 0;
671 try
672 {
674 if (!AreAllBucketsEmpty())
675 {
677 Tables tables2 = (_tables = new Tables(new Node[31], tables._locks, new int[tables._countPerLock.Length]));
678 _budget = Math.Max(1, tables2._buckets.Length / tables2._locks.Length);
679 }
680 }
681 finally
682 {
684 }
685 }
686
688 {
689 if (array == null)
690 {
692 }
693 if (index < 0)
694 {
696 }
697 int locksAcquired = 0;
698 try
699 {
701 int num = 0;
702 int[] countPerLock = _tables._countPerLock;
703 for (int i = 0; i < countPerLock.Length; i++)
704 {
705 if (num < 0)
706 {
707 break;
708 }
709 num += countPerLock[i];
710 }
711 if (array.Length - num < index || num < 0)
712 {
714 }
716 }
717 finally
718 {
720 }
721 }
722
724 {
725 int locksAcquired = 0;
726 try
727 {
729 int num = 0;
730 int[] countPerLock = _tables._countPerLock;
731 for (int i = 0; i < countPerLock.Length; i++)
732 {
733 num = checked(num + countPerLock[i]);
734 }
735 if (num == 0)
736 {
737 return Array.Empty<KeyValuePair<TKey, TValue>>();
738 }
740 CopyToPairs(array, 0);
741 return array;
742 }
743 finally
744 {
746 }
747 }
748
750 {
751 Node[] buckets = _tables._buckets;
752 for (int i = 0; i < buckets.Length; i++)
753 {
754 for (Node node = buckets[i]; node != null; node = node._next)
755 {
756 array[index] = new KeyValuePair<TKey, TValue>(node._key, node._value);
757 index++;
758 }
759 }
760 }
761
763 {
764 Node[] buckets = _tables._buckets;
765 for (int i = 0; i < buckets.Length; i++)
766 {
767 for (Node node = buckets[i]; node != null; node = node._next)
768 {
769 array[index] = new DictionaryEntry(node._key, node._value);
770 index++;
771 }
772 }
773 }
774
775 private void CopyToObjects(object[] array, int index)
776 {
777 Node[] buckets = _tables._buckets;
778 for (int i = 0; i < buckets.Length; i++)
779 {
780 for (Node node = buckets[i]; node != null; node = node._next)
781 {
782 array[index] = new KeyValuePair<TKey, TValue>(node._key, node._value);
783 index++;
784 }
785 }
786 }
787
789 {
790 return new Enumerator(this);
791 }
792
793 private bool TryAddInternal(TKey key, int? nullableHashcode, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)
794 {
796 int num = nullableHashcode ?? comparer?.GetHashCode(key) ?? key.GetHashCode();
797 checked
798 {
800 bool flag;
801 while (true)
802 {
803 tables = _tables;
804 object[] locks = tables._locks;
805 uint lockNo;
806 ref Node bucketAndLock = ref tables.GetBucketAndLock(num, out lockNo);
807 flag = false;
808 bool lockTaken = false;
809 try
810 {
811 if (acquireLock)
812 {
814 }
815 if (tables != _tables)
816 {
817 continue;
818 }
819 Node node = null;
820 for (Node node2 = bucketAndLock; node2 != null; node2 = node2._next)
821 {
822 if (num == node2._hashcode && (comparer?.Equals(node2._key, key) ?? _defaultComparer.Equals(node2._key, key)))
823 {
824 if (updateIfExists)
825 {
827 {
828 node2._value = value;
829 }
830 else
831 {
832 Node node3 = new Node(node2._key, value, num, node2._next);
833 if (node == null)
834 {
836 }
837 else
838 {
839 node._next = node3;
840 }
841 }
843 }
844 else
845 {
846 resultingValue = node2._value;
847 }
848 return false;
849 }
850 node = node2;
851 }
852 Node value2 = new Node(key, value, num, bucketAndLock);
854 tables._countPerLock[lockNo]++;
855 if (tables._countPerLock[lockNo] > _budget)
856 {
857 flag = true;
858 }
859 break;
860 }
861 finally
862 {
863 if (lockTaken)
864 {
866 }
867 }
868 }
869 if (flag)
870 {
872 }
874 return true;
875 }
876 }
877
879 private static void ThrowKeyNotFoundException(TKey key)
880 {
882 }
883
884 private int GetCountInternal()
885 {
886 int num = 0;
887 int[] countPerLock = _tables._countPerLock;
888 for (int i = 0; i < countPerLock.Length; i++)
889 {
890 num += countPerLock[i];
891 }
892 return num;
893 }
894
896 {
897 if (key == null)
898 {
900 }
901 if (valueFactory == null)
902 {
904 }
905 int num = _comparer?.GetHashCode(key) ?? key.GetHashCode();
906 if (!TryGetValueInternal(key, num, out var value))
907 {
909 }
910 return value;
911 }
912
914 {
915 if (key == null)
916 {
918 }
919 if (valueFactory == null)
920 {
922 }
923 int num = _comparer?.GetHashCode(key) ?? key.GetHashCode();
924 if (!TryGetValueInternal(key, num, out var value))
925 {
927 }
928 return value;
929 }
930
931 public TValue GetOrAdd(TKey key, TValue value)
932 {
933 if (key == null)
934 {
936 }
937 int num = _comparer?.GetHashCode(key) ?? key.GetHashCode();
939 {
941 }
942 return value2;
943 }
944
946 {
947 if (key == null)
948 {
950 }
951 if (addValueFactory == null)
952 {
954 }
955 if (updateValueFactory == null)
956 {
957 System.ThrowHelper.ThrowArgumentNullException("updateValueFactory");
958 }
959 int num = _comparer?.GetHashCode(key) ?? key.GetHashCode();
960 TValue resultingValue;
961 while (true)
962 {
964 {
966 if (TryUpdateInternal(key, num, val, value))
967 {
968 return val;
969 }
970 }
972 {
973 break;
974 }
975 }
976 return resultingValue;
977 }
978
980 {
981 if (key == null)
982 {
984 }
985 if (addValueFactory == null)
986 {
988 }
989 if (updateValueFactory == null)
990 {
991 System.ThrowHelper.ThrowArgumentNullException("updateValueFactory");
992 }
993 int num = _comparer?.GetHashCode(key) ?? key.GetHashCode();
994 TValue resultingValue;
995 while (true)
996 {
998 {
999 TValue val = updateValueFactory(key, value);
1000 if (TryUpdateInternal(key, num, val, value))
1001 {
1002 return val;
1003 }
1004 }
1006 {
1007 break;
1008 }
1009 }
1010 return resultingValue;
1011 }
1012
1014 {
1015 if (key == null)
1016 {
1018 }
1019 if (updateValueFactory == null)
1020 {
1021 System.ThrowHelper.ThrowArgumentNullException("updateValueFactory");
1022 }
1023 int num = _comparer?.GetHashCode(key) ?? key.GetHashCode();
1024 TValue resultingValue;
1025 while (true)
1026 {
1027 if (TryGetValueInternal(key, num, out var value))
1028 {
1029 TValue val = updateValueFactory(key, value);
1030 if (TryUpdateInternal(key, num, val, value))
1031 {
1032 return val;
1033 }
1034 }
1035 else if (TryAddInternal(key, num, addValue, updateIfExists: false, acquireLock: true, out resultingValue))
1036 {
1037 break;
1038 }
1039 }
1040 return resultingValue;
1041 }
1042
1044 {
1045 if (!TryAdd(key, value))
1046 {
1048 }
1049 }
1050
1052 {
1053 TValue value;
1054 return TryRemove(key, out value);
1055 }
1056
1061
1063 {
1065 {
1066 return false;
1067 }
1068 return EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value);
1069 }
1070
1075
1077 {
1078 return GetEnumerator();
1079 }
1080
1081 void IDictionary.Add(object key, object value)
1082 {
1083 if (key == null)
1084 {
1086 }
1087 if (!(key is TKey))
1088 {
1090 }
1092 ((IDictionary<TKey, TValue>)this).Add((TKey)key, (TValue)value);
1093 }
1094
1096 {
1097 if (key == null)
1098 {
1100 }
1101 if (key is TKey key2)
1102 {
1103 return ContainsKey(key2);
1104 }
1105 return false;
1106 }
1107
1112
1114 {
1115 if (key == null)
1116 {
1118 }
1119 if (key is TKey key2)
1120 {
1122 }
1123 }
1124
1125 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1126 private static void ThrowIfInvalidObjectValue(object value)
1127 {
1128 if (value != null)
1129 {
1130 if (!(value is TValue))
1131 {
1133 }
1134 }
1135 else if (default(TValue) != null)
1136 {
1138 }
1139 }
1140
1142 {
1143 if (array == null)
1144 {
1146 }
1147 if (index < 0)
1148 {
1150 }
1151 int locksAcquired = 0;
1152 try
1153 {
1156 int num = 0;
1157 int[] countPerLock = tables._countPerLock;
1158 for (int i = 0; i < countPerLock.Length; i++)
1159 {
1160 if (num < 0)
1161 {
1162 break;
1163 }
1164 num += countPerLock[i];
1165 }
1166 if (array.Length - num < index || num < 0)
1167 {
1169 }
1171 {
1173 return;
1174 }
1176 {
1178 return;
1179 }
1180 if (array is object[] array4)
1181 {
1183 return;
1184 }
1186 }
1187 finally
1188 {
1190 }
1191 }
1192
1193 private bool AreAllBucketsEmpty()
1194 {
1195 int[] countPerLock = _tables._countPerLock;
1196 for (int i = 0; i < countPerLock.Length; i++)
1197 {
1198 if (countPerLock[i] != 0)
1199 {
1200 return false;
1201 }
1202 }
1203 return true;
1204 }
1205
1207 {
1208 int locksAcquired = 0;
1209 try
1210 {
1212 if (tables != _tables)
1213 {
1214 return;
1215 }
1216 long num = 0L;
1217 for (int i = 0; i < tables._countPerLock.Length; i++)
1218 {
1219 num += tables._countPerLock[i];
1220 }
1221 if (num < tables._buckets.Length / 4)
1222 {
1223 _budget = 2 * _budget;
1224 if (_budget < 0)
1225 {
1226 _budget = int.MaxValue;
1227 }
1228 return;
1229 }
1230 int j = 0;
1231 bool flag = false;
1232 try
1233 {
1234 for (j = checked(tables._buckets.Length * 2 + 1); j % 3 == 0 || j % 5 == 0 || j % 7 == 0; j = checked(j + 2))
1235 {
1236 }
1237 if (j > Array.MaxLength)
1238 {
1239 flag = true;
1240 }
1241 }
1242 catch (OverflowException)
1243 {
1244 flag = true;
1245 }
1246 if (flag)
1247 {
1248 j = Array.MaxLength;
1249 _budget = int.MaxValue;
1250 }
1251 AcquireLocks(1, tables._locks.Length, ref locksAcquired);
1252 object[] array = tables._locks;
1253 if (_growLockArray && tables._locks.Length < 1024)
1254 {
1255 array = new object[tables._locks.Length * 2];
1256 Array.Copy(tables._locks, array, tables._locks.Length);
1257 for (int k = tables._locks.Length; k < array.Length; k++)
1258 {
1259 array[k] = new object();
1260 }
1261 }
1262 Node[] array2 = new Node[j];
1263 int[] array3 = new int[array.Length];
1265 Node[] buckets = tables._buckets;
1266 checked
1267 {
1268 foreach (Node node in buckets)
1269 {
1270 Node node2 = node;
1271 while (node2 != null)
1272 {
1273 Node next = node2._next;
1274 uint lockNo;
1275 ref Node bucketAndLock = ref tables2.GetBucketAndLock(node2._hashcode, out lockNo);
1276 bucketAndLock = new Node(node2._key, node2._value, node2._hashcode, bucketAndLock);
1277 array3[lockNo]++;
1278 node2 = next;
1279 }
1280 }
1281 }
1282 _budget = Math.Max(1, array2.Length / array.Length);
1283 _tables = tables2;
1284 }
1285 finally
1286 {
1288 }
1289 }
1290
1292 {
1293 if (CDSCollectionETWBCLProvider.Log.IsEnabled())
1294 {
1295 CDSCollectionETWBCLProvider.Log.ConcurrentDictionary_AcquiringAllLocks(_tables._buckets.Length);
1296 }
1298 AcquireLocks(1, _tables._locks.Length, ref locksAcquired);
1299 }
1300
1302 {
1303 object[] locks = _tables._locks;
1304 for (int i = fromInclusive; i < toExclusive; i++)
1305 {
1306 bool lockTaken = false;
1307 try
1308 {
1310 }
1311 finally
1312 {
1313 if (lockTaken)
1314 {
1315 locksAcquired++;
1316 }
1317 }
1318 }
1319 }
1320
1322 {
1324 for (int i = fromInclusive; i < toExclusive; i++)
1325 {
1326 Monitor.Exit(tables._locks[i]);
1327 }
1328 }
1329
1331 {
1332 int locksAcquired = 0;
1333 try
1334 {
1337 if (countInternal < 0)
1338 {
1340 }
1342 Node[] buckets = _tables._buckets;
1343 for (int i = 0; i < buckets.Length; i++)
1344 {
1345 for (Node node = buckets[i]; node != null; node = node._next)
1346 {
1347 list.Add(node._key);
1348 }
1349 }
1350 return new ReadOnlyCollection<TKey>(list);
1351 }
1352 finally
1353 {
1355 }
1356 }
1357
1359 {
1360 int locksAcquired = 0;
1361 try
1362 {
1365 if (countInternal < 0)
1366 {
1368 }
1370 Node[] buckets = _tables._buckets;
1371 for (int i = 0; i < buckets.Length; i++)
1372 {
1373 for (Node node = buckets[i]; node != null; node = node._next)
1374 {
1375 list.Add(node._value);
1376 }
1377 }
1378 return new ReadOnlyCollection<TValue>(list);
1379 }
1380 finally
1381 {
1383 }
1384 }
1385}
static int MaxLength
Definition Array.cs:471
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
DictionaryEnumerator(ConcurrentDictionary< TKey, TValue > dictionary)
readonly IEnumerator< KeyValuePair< TKey, TValue > > _enumerator
readonly ConcurrentDictionary< TKey, TValue > _dictionary
Enumerator(ConcurrentDictionary< TKey, TValue > dictionary)
Node(TKey key, TValue value, int hashcode, Node next)
Tables(Node[] buckets, object[] locks, int[] countPerLock)
bool TryRemoveInternal(TKey key, [MaybeNullWhen(false)] out TValue value, bool matchValue, TValue oldValue)
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
TValue AddOrUpdate(TKey key, Func< TKey, TValue > addValueFactory, Func< TKey, TValue, TValue > updateValueFactory)
ConcurrentDictionary(IEqualityComparer< TKey >? comparer)
void CopyToPairs(KeyValuePair< TKey, TValue >[] array, int index)
TValue AddOrUpdate(TKey key, TValue addValue, Func< TKey, TValue, TValue > updateValueFactory)
bool TryAddInternal(TKey key, int? nullableHashcode, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)
TValue GetOrAdd< TArg >(TKey key, Func< TKey, TArg, TValue > valueFactory, TArg factoryArgument)
bool TryUpdateInternal(TKey key, int? nullableHashcode, TValue newValue, TValue comparisonValue)
IEnumerator< KeyValuePair< TKey, TValue > > GetEnumerator()
ConcurrentDictionary(int concurrencyLevel, IEnumerable< KeyValuePair< TKey, TValue > > collection, IEqualityComparer< TKey >? comparer)
void CopyToEntries(DictionaryEntry[] array, int index)
ConcurrentDictionary(IEnumerable< KeyValuePair< TKey, TValue > > collection, IEqualityComparer< TKey >? comparer)
ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer< TKey >? comparer)
void InitializeFromCollection(IEnumerable< KeyValuePair< TKey, TValue > > collection)
TValue AddOrUpdate< TArg >(TKey key, Func< TKey, TArg, TValue > addValueFactory, Func< TKey, TValue, TArg, TValue > updateValueFactory, TArg factoryArgument)
bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
ConcurrentDictionary(IEnumerable< KeyValuePair< TKey, TValue > > collection)
void ReleaseLocks(int fromInclusive, int toExclusive)
ConcurrentDictionary(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer< TKey > comparer)
bool TryGetValueInternal(TKey key, int hashcode, [MaybeNullWhen(false)] out TValue value)
ConcurrentDictionary(int concurrencyLevel, int capacity)
void AcquireLocks(int fromInclusive, int toExclusive, ref int locksAcquired)
bool TryRemove(KeyValuePair< TKey, TValue > item)
bool TryRemove(TKey key, [MaybeNullWhen(false)] out TValue value)
TValue GetOrAdd(TKey key, Func< TKey, TValue > valueFactory)
bool ICollection< KeyValuePair< TKey, TValue > >. Remove(KeyValuePair< TKey, TValue > keyValuePair)
void CopyTo(KeyValuePair< TKey, TValue >[] array, int index)
bool ICollection< KeyValuePair< TKey, TValue > >. Contains(KeyValuePair< TKey, TValue > keyValuePair)
bool ICollection< KeyValuePair< TKey, TValue > >. IsReadOnly
void Add(TKey key, TValue value)
static uint FastMod(uint value, uint divisor, ulong multiplier)
static ulong GetFastModMultiplier(uint divisor)
Definition HashHelpers.cs:7
static int ProcessorCount
static byte Max(byte val1, byte val2)
Definition Math.cs:738
static string ConcurrentDictionary_ConcurrencyLevelMustBePositive
Definition SR.cs:64
static string ConcurrentCollection_SyncRoot_NotSupported
Definition SR.cs:58
static string ConcurrentDictionary_ArrayIncorrectType
Definition SR.cs:60
static string ConcurrentDictionary_KeyAlreadyExisted
Definition SR.cs:72
static string ConcurrentDictionary_TypeOfKeyIncorrect
Definition SR.cs:76
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string ConcurrentDictionary_ItemKeyIsNull
Definition SR.cs:74
static string ConcurrentDictionary_SourceContainsDuplicateKeys
Definition SR.cs:62
static string ConcurrentDictionary_ArrayNotLargeEnough
Definition SR.cs:70
static string ConcurrentDictionary_CapacityMustNotBeNegative
Definition SR.cs:66
static string ConcurrentDictionary_IndexIsNegative
Definition SR.cs:68
static string Arg_KeyNotFoundWithKey
Definition SR.cs:94
Definition SR.cs:7
static StringComparer Ordinal
static void Exit(object obj)
static void Enter(object obj)
static bool Read(ref bool location)
Definition Volatile.cs:67
static void Write(ref bool location, bool value)
Definition Volatile.cs:74
static void ThrowKeyNullException()
Definition ThrowHelper.cs:8
static void ThrowOutOfMemoryException()
static void ThrowValueNullException()
static void ThrowArgumentNullException(string name)
static TypeCode GetTypeCode(Type? type)
Definition Type.cs:919
void CopyTo(Array array, int index)
new IDictionaryEnumerator GetEnumerator()
void Add(object key, object? value)
TypeCode
Definition TypeCode.cs:4
static int Size
Definition IntPtr.cs:21