1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.jboss.netty.util.internal;
22
23 import java.util.AbstractCollection;
24 import java.util.AbstractMap;
25 import java.util.AbstractSet;
26 import java.util.Collection;
27 import java.util.ConcurrentModificationException;
28 import java.util.Enumeration;
29 import java.util.Hashtable;
30 import java.util.Iterator;
31 import java.util.Map;
32 import java.util.NoSuchElementException;
33 import java.util.Set;
34 import java.util.concurrent.ConcurrentMap;
35 import java.util.concurrent.locks.ReentrantLock;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public final class ConcurrentIdentityHashMap<K, V> extends AbstractMap<K, V>
52 implements ConcurrentMap<K, V>{
53
54
55
56
57
58 static final int DEFAULT_INITIAL_CAPACITY = 16;
59
60
61
62
63
64 static final float DEFAULT_LOAD_FACTOR = 0.75f;
65
66
67
68
69
70 static final int DEFAULT_CONCURRENCY_LEVEL = 16;
71
72
73
74
75
76
77 static final int MAXIMUM_CAPACITY = 1 << 30;
78
79
80
81
82
83 static final int MAX_SEGMENTS = 1 << 16;
84
85
86
87
88
89
90
91 static final int RETRIES_BEFORE_LOCK = 2;
92
93
94
95
96
97
98
99 final int segmentMask;
100
101
102
103
104 final int segmentShift;
105
106
107
108
109 final Segment<K, V>[] segments;
110
111 Set<K> keySet;
112 Set<Map.Entry<K, V>> entrySet;
113 Collection<V> values;
114
115
116
117
118
119
120
121
122
123
124 private static int hash(int h) {
125
126
127 h += h << 15 ^ 0xffffcd7d;
128 h ^= h >>> 10;
129 h += h << 3;
130 h ^= h >>> 6;
131 h += (h << 2) + (h << 14);
132 return h ^ h >>> 16;
133 }
134
135
136
137
138
139
140
141 final Segment<K, V> segmentFor(int hash) {
142 return segments[hash >>> segmentShift & segmentMask];
143 }
144
145 private int hashOf(Object key) {
146 return hash(System.identityHashCode(key));
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161 static final class HashEntry<K, V> {
162 final Object key;
163 final int hash;
164 volatile Object value;
165 final HashEntry<K, V> next;
166
167 HashEntry(
168 K key, int hash, HashEntry<K, V> next, V value) {
169 this.hash = hash;
170 this.next = next;
171 this.key = key;
172 this.value = value;
173 }
174
175 @SuppressWarnings("unchecked")
176 final K key() {
177 return (K) key;
178 }
179
180 @SuppressWarnings("unchecked")
181 final V value() {
182 return (V) value;
183 }
184
185 final void setValue(V value) {
186 this.value = value;
187 }
188
189 @SuppressWarnings("unchecked")
190 static final <K, V> HashEntry<K, V>[] newArray(int i) {
191 return new HashEntry[i];
192 }
193 }
194
195
196
197
198
199
200 static final class Segment<K, V> extends ReentrantLock {
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236 private static final long serialVersionUID = 5207829234977119743L;
237
238
239
240
241 transient volatile int count;
242
243
244
245
246
247
248
249
250 int modCount;
251
252
253
254
255
256 int threshold;
257
258
259
260
261 transient volatile HashEntry<K, V>[] table;
262
263
264
265
266
267
268 final float loadFactor;
269
270 Segment(int initialCapacity, float lf) {
271 loadFactor = lf;
272 setTable(HashEntry.<K, V> newArray(initialCapacity));
273 }
274
275 @SuppressWarnings("unchecked")
276 static final <K, V> Segment<K, V>[] newArray(int i) {
277 return new Segment[i];
278 }
279
280 private boolean keyEq(Object src, Object dest) {
281 return src == dest;
282 }
283
284
285
286
287
288 void setTable(HashEntry<K, V>[] newTable) {
289 threshold = (int) (newTable.length * loadFactor);
290 table = newTable;
291 }
292
293
294
295
296 HashEntry<K, V> getFirst(int hash) {
297 HashEntry<K, V>[] tab = table;
298 return tab[hash & tab.length - 1];
299 }
300
301 HashEntry<K, V> newHashEntry(
302 K key, int hash, HashEntry<K, V> next, V value) {
303 return new HashEntry<K, V>(key, hash, next, value);
304 }
305
306
307
308
309
310
311
312 V readValueUnderLock(HashEntry<K, V> e) {
313 lock();
314 try {
315 return e.value();
316 } finally {
317 unlock();
318 }
319 }
320
321
322
323 V get(Object key, int hash) {
324 if (count != 0) {
325 HashEntry<K, V> e = getFirst(hash);
326 while (e != null) {
327 if (e.hash == hash && keyEq(key, e.key())) {
328 V opaque = e.value();
329 if (opaque != null) {
330 return opaque;
331 }
332
333 return readValueUnderLock(e);
334 }
335 e = e.next;
336 }
337 }
338 return null;
339 }
340
341 boolean containsKey(Object key, int hash) {
342 if (count != 0) {
343 HashEntry<K, V> e = getFirst(hash);
344 while (e != null) {
345 if (e.hash == hash && keyEq(key, e.key())) {
346 return true;
347 }
348 e = e.next;
349 }
350 }
351 return false;
352 }
353
354 boolean containsValue(Object value) {
355 if (count != 0) {
356 HashEntry<K, V>[] tab = table;
357 int len = tab.length;
358 for (int i = 0; i < len; i ++) {
359 for (HashEntry<K, V> e = tab[i]; e != null; e = e.next) {
360 V opaque = e.value();
361 V v;
362
363 if (opaque == null) {
364 v = readValueUnderLock(e);
365 } else {
366 v = opaque;
367 }
368
369 if (value.equals(v)) {
370 return true;
371 }
372 }
373 }
374 }
375 return false;
376 }
377
378 boolean replace(K key, int hash, V oldValue, V newValue) {
379 lock();
380 try {
381 HashEntry<K, V> e = getFirst(hash);
382 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
383 e = e.next;
384 }
385
386 boolean replaced = false;
387 if (e != null && oldValue.equals(e.value())) {
388 replaced = true;
389 e.setValue(newValue);
390 }
391 return replaced;
392 } finally {
393 unlock();
394 }
395 }
396
397 V replace(K key, int hash, V newValue) {
398 lock();
399 try {
400 HashEntry<K, V> e = getFirst(hash);
401 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
402 e = e.next;
403 }
404
405 V oldValue = null;
406 if (e != null) {
407 oldValue = e.value();
408 e.setValue(newValue);
409 }
410 return oldValue;
411 } finally {
412 unlock();
413 }
414 }
415
416 V put(K key, int hash, V value, boolean onlyIfAbsent) {
417 lock();
418 try {
419 int c = count;
420 if (c ++ > threshold) {
421 int reduced = rehash();
422 if (reduced > 0) {
423 count = (c -= reduced) - 1;
424 }
425 }
426
427 HashEntry<K, V>[] tab = table;
428 int index = hash & tab.length - 1;
429 HashEntry<K, V> first = tab[index];
430 HashEntry<K, V> e = first;
431 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
432 e = e.next;
433 }
434
435 V oldValue;
436 if (e != null) {
437 oldValue = e.value();
438 if (!onlyIfAbsent) {
439 e.setValue(value);
440 }
441 } else {
442 oldValue = null;
443 ++ modCount;
444 tab[index] = newHashEntry(key, hash, first, value);
445 count = c;
446 }
447 return oldValue;
448 } finally {
449 unlock();
450 }
451 }
452
453 int rehash() {
454 HashEntry<K, V>[] oldTable = table;
455 int oldCapacity = oldTable.length;
456 if (oldCapacity >= MAXIMUM_CAPACITY) {
457 return 0;
458 }
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473 HashEntry<K, V>[] newTable = HashEntry.newArray(oldCapacity << 1);
474 threshold = (int) (newTable.length * loadFactor);
475 int sizeMask = newTable.length - 1;
476 int reduce = 0;
477 for (int i = 0; i < oldCapacity; i ++) {
478
479
480 HashEntry<K, V> e = oldTable[i];
481
482 if (e != null) {
483 HashEntry<K, V> next = e.next;
484 int idx = e.hash & sizeMask;
485
486
487 if (next == null) {
488 newTable[idx] = e;
489 } else {
490
491 HashEntry<K, V> lastRun = e;
492 int lastIdx = idx;
493 for (HashEntry<K, V> last = next; last != null; last = last.next) {
494 int k = last.hash & sizeMask;
495 if (k != lastIdx) {
496 lastIdx = k;
497 lastRun = last;
498 }
499 }
500 newTable[lastIdx] = lastRun;
501
502 for (HashEntry<K, V> p = e; p != lastRun; p = p.next) {
503
504 K key = p.key();
505 if (key == null) {
506 reduce ++;
507 continue;
508 }
509 int k = p.hash & sizeMask;
510 HashEntry<K, V> n = newTable[k];
511 newTable[k] = newHashEntry(key, p.hash, n, p.value());
512 }
513 }
514 }
515 }
516 table = newTable;
517 return reduce;
518 }
519
520
521
522
523 V remove(Object key, int hash, Object value, boolean refRemove) {
524 lock();
525 try {
526 int c = count - 1;
527 HashEntry<K, V>[] tab = table;
528 int index = hash & tab.length - 1;
529 HashEntry<K, V> first = tab[index];
530 HashEntry<K, V> e = first;
531
532 while (e != null && key != e.key &&
533 (refRemove || hash != e.hash || !keyEq(key, e.key()))) {
534 e = e.next;
535 }
536
537 V oldValue = null;
538 if (e != null) {
539 V v = e.value();
540 if (value == null || value.equals(v)) {
541 oldValue = v;
542
543
544 ++ modCount;
545 HashEntry<K, V> newFirst = e.next;
546 for (HashEntry<K, V> p = first; p != e; p = p.next) {
547 K pKey = p.key();
548 if (pKey == null) {
549 c --;
550 continue;
551 }
552
553 newFirst = newHashEntry(
554 pKey, p.hash, newFirst, p.value());
555 }
556 tab[index] = newFirst;
557 count = c;
558 }
559 }
560 return oldValue;
561 } finally {
562 unlock();
563 }
564 }
565
566 void clear() {
567 if (count != 0) {
568 lock();
569 try {
570 HashEntry<K, V>[] tab = table;
571 for (int i = 0; i < tab.length; i ++) {
572 tab[i] = null;
573 }
574 ++ modCount;
575 count = 0;
576 } finally {
577 unlock();
578 }
579 }
580 }
581 }
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601 public ConcurrentIdentityHashMap(
602 int initialCapacity, float loadFactor,
603 int concurrencyLevel) {
604 if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) {
605 throw new IllegalArgumentException();
606 }
607
608 if (concurrencyLevel > MAX_SEGMENTS) {
609 concurrencyLevel = MAX_SEGMENTS;
610 }
611
612
613 int sshift = 0;
614 int ssize = 1;
615 while (ssize < concurrencyLevel) {
616 ++ sshift;
617 ssize <<= 1;
618 }
619 segmentShift = 32 - sshift;
620 segmentMask = ssize - 1;
621 this.segments = Segment.newArray(ssize);
622
623 if (initialCapacity > MAXIMUM_CAPACITY) {
624 initialCapacity = MAXIMUM_CAPACITY;
625 }
626 int c = initialCapacity / ssize;
627 if (c * ssize < initialCapacity) {
628 ++ c;
629 }
630 int cap = 1;
631 while (cap < c) {
632 cap <<= 1;
633 }
634
635 for (int i = 0; i < this.segments.length; ++ i) {
636 this.segments[i] = new Segment<K, V>(cap, loadFactor);
637 }
638 }
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655 public ConcurrentIdentityHashMap(int initialCapacity, float loadFactor) {
656 this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
657 }
658
659
660
661
662
663
664
665
666
667
668
669 public ConcurrentIdentityHashMap(int initialCapacity) {
670 this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
671 }
672
673
674
675
676
677
678 public ConcurrentIdentityHashMap() {
679 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
680 }
681
682
683
684
685
686
687
688
689
690 public ConcurrentIdentityHashMap(Map<? extends K, ? extends V> m) {
691 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
692 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR,
693 DEFAULT_CONCURRENCY_LEVEL);
694 putAll(m);
695 }
696
697
698
699
700
701
702 @Override
703 public boolean isEmpty() {
704 final Segment<K, V>[] segments = this.segments;
705
706
707
708
709
710
711
712
713 int[] mc = new int[segments.length];
714 int mcsum = 0;
715 for (int i = 0; i < segments.length; ++ i) {
716 if (segments[i].count != 0) {
717 return false;
718 } else {
719 mcsum += mc[i] = segments[i].modCount;
720 }
721 }
722
723
724
725 if (mcsum != 0) {
726 for (int i = 0; i < segments.length; ++ i) {
727 if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
728 return false;
729 }
730 }
731 }
732 return true;
733 }
734
735
736
737
738
739
740
741
742 @Override
743 public int size() {
744 final Segment<K, V>[] segments = this.segments;
745 long sum = 0;
746 long check = 0;
747 int[] mc = new int[segments.length];
748
749
750 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
751 check = 0;
752 sum = 0;
753 int mcsum = 0;
754 for (int i = 0; i < segments.length; ++ i) {
755 sum += segments[i].count;
756 mcsum += mc[i] = segments[i].modCount;
757 }
758 if (mcsum != 0) {
759 for (int i = 0; i < segments.length; ++ i) {
760 check += segments[i].count;
761 if (mc[i] != segments[i].modCount) {
762 check = -1;
763 break;
764 }
765 }
766 }
767 if (check == sum) {
768 break;
769 }
770 }
771 if (check != sum) {
772 sum = 0;
773 for (int i = 0; i < segments.length; ++ i) {
774 segments[i].lock();
775 }
776 for (int i = 0; i < segments.length; ++ i) {
777 sum += segments[i].count;
778 }
779 for (int i = 0; i < segments.length; ++ i) {
780 segments[i].unlock();
781 }
782 }
783 if (sum > Integer.MAX_VALUE) {
784 return Integer.MAX_VALUE;
785 } else {
786 return (int) sum;
787 }
788 }
789
790
791
792
793
794
795
796
797
798
799
800
801 @Override
802 public V get(Object key) {
803 int hash = hashOf(key);
804 return segmentFor(hash).get(key, hash);
805 }
806
807
808
809
810
811
812
813
814
815
816 @Override
817 public boolean containsKey(Object key) {
818 int hash = hashOf(key);
819 return segmentFor(hash).containsKey(key, hash);
820 }
821
822
823
824
825
826
827
828
829
830
831
832
833 @Override
834 public boolean containsValue(Object value) {
835 if (value == null) {
836 throw new NullPointerException();
837 }
838
839
840
841 final Segment<K, V>[] segments = this.segments;
842 int[] mc = new int[segments.length];
843
844
845 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
846 int mcsum = 0;
847 for (int i = 0; i < segments.length; ++ i) {
848 mcsum += mc[i] = segments[i].modCount;
849 if (segments[i].containsValue(value)) {
850 return true;
851 }
852 }
853 boolean cleanSweep = true;
854 if (mcsum != 0) {
855 for (int i = 0; i < segments.length; ++ i) {
856 if (mc[i] != segments[i].modCount) {
857 cleanSweep = false;
858 break;
859 }
860 }
861 }
862 if (cleanSweep) {
863 return false;
864 }
865 }
866
867 for (int i = 0; i < segments.length; ++ i) {
868 segments[i].lock();
869 }
870 boolean found = false;
871 try {
872 for (int i = 0; i < segments.length; ++ i) {
873 if (segments[i].containsValue(value)) {
874 found = true;
875 break;
876 }
877 }
878 } finally {
879 for (int i = 0; i < segments.length; ++ i) {
880 segments[i].unlock();
881 }
882 }
883 return found;
884 }
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899 public boolean contains(Object value) {
900 return containsValue(value);
901 }
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916 @Override
917 public V put(K key, V value) {
918 if (value == null) {
919 throw new NullPointerException();
920 }
921 int hash = hashOf(key);
922 return segmentFor(hash).put(key, hash, value, false);
923 }
924
925
926
927
928
929
930
931
932 public V putIfAbsent(K key, V value) {
933 if (value == null) {
934 throw new NullPointerException();
935 }
936 int hash = hashOf(key);
937 return segmentFor(hash).put(key, hash, value, true);
938 }
939
940
941
942
943
944
945
946
947 @Override
948 public void putAll(Map<? extends K, ? extends V> m) {
949 for (Map.Entry<? extends K, ? extends V> e: m.entrySet()) {
950 put(e.getKey(), e.getValue());
951 }
952 }
953
954
955
956
957
958
959
960
961
962
963 @Override
964 public V remove(Object key) {
965 int hash = hashOf(key);
966 return segmentFor(hash).remove(key, hash, null, false);
967 }
968
969
970
971
972
973
974 public boolean remove(Object key, Object value) {
975 int hash = hashOf(key);
976 if (value == null) {
977 return false;
978 }
979 return segmentFor(hash).remove(key, hash, value, false) != null;
980 }
981
982
983
984
985
986
987 public boolean replace(K key, V oldValue, V newValue) {
988 if (oldValue == null || newValue == null) {
989 throw new NullPointerException();
990 }
991 int hash = hashOf(key);
992 return segmentFor(hash).replace(key, hash, oldValue, newValue);
993 }
994
995
996
997
998
999
1000
1001
1002 public V replace(K key, V value) {
1003 if (value == null) {
1004 throw new NullPointerException();
1005 }
1006 int hash = hashOf(key);
1007 return segmentFor(hash).replace(key, hash, value);
1008 }
1009
1010
1011
1012
1013 @Override
1014 public void clear() {
1015 for (int i = 0; i < segments.length; ++ i) {
1016 segments[i].clear();
1017 }
1018 }
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 @Override
1036 public Set<K> keySet() {
1037 Set<K> ks = keySet;
1038 return ks != null? ks : (keySet = new KeySet());
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 @Override
1057 public Collection<V> values() {
1058 Collection<V> vs = values;
1059 return vs != null? vs : (values = new Values());
1060 }
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077 @Override
1078 public Set<Map.Entry<K, V>> entrySet() {
1079 Set<Map.Entry<K, V>> es = entrySet;
1080 return es != null? es : (entrySet = new EntrySet());
1081 }
1082
1083
1084
1085
1086
1087
1088
1089 public Enumeration<K> keys() {
1090 return new KeyIterator();
1091 }
1092
1093
1094
1095
1096
1097
1098
1099 public Enumeration<V> elements() {
1100 return new ValueIterator();
1101 }
1102
1103
1104
1105 abstract class HashIterator {
1106 int nextSegmentIndex;
1107 int nextTableIndex;
1108 HashEntry<K, V>[] currentTable;
1109 HashEntry<K, V> nextEntry;
1110 HashEntry<K, V> lastReturned;
1111 K currentKey;
1112
1113 HashIterator() {
1114 nextSegmentIndex = segments.length - 1;
1115 nextTableIndex = -1;
1116 advance();
1117 }
1118
1119 public void rewind() {
1120 nextSegmentIndex = segments.length - 1;
1121 nextTableIndex = -1;
1122 currentTable = null;
1123 nextEntry = null;
1124 lastReturned = null;
1125 currentKey = null;
1126 advance();
1127 }
1128
1129 public boolean hasMoreElements() {
1130 return hasNext();
1131 }
1132
1133 final void advance() {
1134 if (nextEntry != null && (nextEntry = nextEntry.next) != null) {
1135 return;
1136 }
1137
1138 while (nextTableIndex >= 0) {
1139 if ((nextEntry = currentTable[nextTableIndex --]) != null) {
1140 return;
1141 }
1142 }
1143
1144 while (nextSegmentIndex >= 0) {
1145 Segment<K, V> seg = segments[nextSegmentIndex --];
1146 if (seg.count != 0) {
1147 currentTable = seg.table;
1148 for (int j = currentTable.length - 1; j >= 0; -- j) {
1149 if ((nextEntry = currentTable[j]) != null) {
1150 nextTableIndex = j - 1;
1151 return;
1152 }
1153 }
1154 }
1155 }
1156 }
1157
1158 public boolean hasNext() {
1159 while (nextEntry != null) {
1160 if (nextEntry.key() != null) {
1161 return true;
1162 }
1163 advance();
1164 }
1165
1166 return false;
1167 }
1168
1169 HashEntry<K, V> nextEntry() {
1170 do {
1171 if (nextEntry == null) {
1172 throw new NoSuchElementException();
1173 }
1174
1175 lastReturned = nextEntry;
1176 currentKey = lastReturned.key();
1177 advance();
1178 } while (currentKey == null);
1179
1180 return lastReturned;
1181 }
1182
1183 public void remove() {
1184 if (lastReturned == null) {
1185 throw new IllegalStateException();
1186 }
1187 ConcurrentIdentityHashMap.this.remove(currentKey);
1188 lastReturned = null;
1189 }
1190 }
1191
1192 final class KeyIterator
1193 extends HashIterator implements ReusableIterator<K>, Enumeration<K> {
1194
1195 public K next() {
1196 return super.nextEntry().key();
1197 }
1198
1199 public K nextElement() {
1200 return super.nextEntry().key();
1201 }
1202 }
1203
1204 final class ValueIterator
1205 extends HashIterator implements ReusableIterator<V>, Enumeration<V> {
1206
1207 public V next() {
1208 return super.nextEntry().value();
1209 }
1210
1211 public V nextElement() {
1212 return super.nextEntry().value();
1213 }
1214 }
1215
1216
1217
1218
1219 static class SimpleEntry<K, V> implements Entry<K, V> {
1220
1221 private static final long serialVersionUID = -8144765946475398746L;
1222
1223 private final K key;
1224
1225 private V value;
1226
1227 public SimpleEntry(K key, V value) {
1228 this.key = key;
1229 this.value = value;
1230
1231 }
1232
1233 public SimpleEntry(Entry<? extends K, ? extends V> entry) {
1234 this.key = entry.getKey();
1235 this.value = entry.getValue();
1236
1237 }
1238
1239 public K getKey() {
1240 return key;
1241 }
1242
1243 public V getValue() {
1244 return value;
1245 }
1246
1247 public V setValue(V value) {
1248 V oldValue = this.value;
1249 this.value = value;
1250 return oldValue;
1251 }
1252
1253 @Override
1254 public boolean equals(Object o) {
1255 if (!(o instanceof Map.Entry<?, ?>)) {
1256 return false;
1257 }
1258 @SuppressWarnings("rawtypes")
1259 Map.Entry e = (Map.Entry) o;
1260 return eq(key, e.getKey()) && eq(value, e.getValue());
1261 }
1262
1263 @Override
1264 public int hashCode() {
1265 return (key == null? 0 : key.hashCode()) ^ (value == null? 0 : value.hashCode());
1266 }
1267
1268 @Override
1269 public String toString() {
1270 return key + "=" + value;
1271 }
1272
1273 private static boolean eq(Object o1, Object o2) {
1274 return o1 == null? o2 == null : o1.equals(o2);
1275 }
1276 }
1277
1278
1279
1280
1281
1282 final class WriteThroughEntry extends SimpleEntry<K, V> {
1283
1284 WriteThroughEntry(K k, V v) {
1285 super(k, v);
1286 }
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296 @Override
1297 public V setValue(V value) {
1298
1299 if (value == null) {
1300 throw new NullPointerException();
1301 }
1302 V v = super.setValue(value);
1303 ConcurrentIdentityHashMap.this.put(getKey(), value);
1304 return v;
1305 }
1306
1307 }
1308
1309 final class EntryIterator extends HashIterator implements
1310 ReusableIterator<Entry<K, V>> {
1311 public Map.Entry<K, V> next() {
1312 HashEntry<K, V> e = super.nextEntry();
1313 return new WriteThroughEntry(e.key(), e.value());
1314 }
1315 }
1316
1317 final class KeySet extends AbstractSet<K> {
1318 @Override
1319 public Iterator<K> iterator() {
1320
1321 return new KeyIterator();
1322 }
1323
1324 @Override
1325 public int size() {
1326 return ConcurrentIdentityHashMap.this.size();
1327 }
1328
1329 @Override
1330 public boolean isEmpty() {
1331 return ConcurrentIdentityHashMap.this.isEmpty();
1332 }
1333
1334 @Override
1335 public boolean contains(Object o) {
1336 return ConcurrentIdentityHashMap.this.containsKey(o);
1337 }
1338
1339 @Override
1340 public boolean remove(Object o) {
1341 return ConcurrentIdentityHashMap.this.remove(o) != null;
1342
1343 }
1344
1345 @Override
1346 public void clear() {
1347 ConcurrentIdentityHashMap.this.clear();
1348 }
1349 }
1350
1351 final class Values extends AbstractCollection<V> {
1352 @Override
1353 public Iterator<V> iterator() {
1354 return new ValueIterator();
1355 }
1356
1357 @Override
1358 public int size() {
1359 return ConcurrentIdentityHashMap.this.size();
1360 }
1361
1362 @Override
1363 public boolean isEmpty() {
1364 return ConcurrentIdentityHashMap.this.isEmpty();
1365 }
1366
1367 @Override
1368 public boolean contains(Object o) {
1369 return ConcurrentIdentityHashMap.this.containsValue(o);
1370 }
1371
1372 @Override
1373 public void clear() {
1374 ConcurrentIdentityHashMap.this.clear();
1375 }
1376 }
1377
1378 final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
1379 @Override
1380 public Iterator<Map.Entry<K, V>> iterator() {
1381 return new EntryIterator();
1382 }
1383
1384 @Override
1385 public boolean contains(Object o) {
1386 if (!(o instanceof Map.Entry<?, ?>)) {
1387 return false;
1388 }
1389 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1390 V v = ConcurrentIdentityHashMap.this.get(e.getKey());
1391 return v != null && v.equals(e.getValue());
1392 }
1393
1394 @Override
1395 public boolean remove(Object o) {
1396 if (!(o instanceof Map.Entry<?, ?>)) {
1397 return false;
1398 }
1399 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1400 return ConcurrentIdentityHashMap.this.remove(e.getKey(), e.getValue());
1401 }
1402
1403 @Override
1404 public int size() {
1405 return ConcurrentIdentityHashMap.this.size();
1406 }
1407
1408 @Override
1409 public boolean isEmpty() {
1410 return ConcurrentIdentityHashMap.this.isEmpty();
1411 }
1412
1413 @Override
1414 public void clear() {
1415 ConcurrentIdentityHashMap.this.clear();
1416 }
1417 }
1418 }