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