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.ConcurrentMap;
36 import java.util.concurrent.locks.ReentrantLock;
37
38
39
40
41
42
43
44
45 public final class ConcurrentIdentityHashMap<K, V> extends AbstractMap<K, V>
46 implements ConcurrentMap<K, V> {
47
48
49
50
51
52 static final int DEFAULT_INITIAL_CAPACITY = 16;
53
54
55
56
57
58 static final float DEFAULT_LOAD_FACTOR = 0.75f;
59
60
61
62
63
64 static final int DEFAULT_CONCURRENCY_LEVEL = 16;
65
66
67
68
69
70
71 static final int MAXIMUM_CAPACITY = 1 << 30;
72
73
74
75
76
77 static final int MAX_SEGMENTS = 1 << 16;
78
79
80
81
82
83
84
85 static final int RETRIES_BEFORE_LOCK = 2;
86
87
88
89
90
91
92
93 final int segmentMask;
94
95
96
97
98 final int segmentShift;
99
100
101
102
103 final Segment<K, V>[] segments;
104
105 Set<K> keySet;
106 Set<Map.Entry<K, V>> entrySet;
107 Collection<V> values;
108
109
110
111
112
113
114
115
116
117
118 private static int hash(int h) {
119
120
121 h += h << 15 ^ 0xffffcd7d;
122 h ^= h >>> 10;
123 h += h << 3;
124 h ^= h >>> 6;
125 h += (h << 2) + (h << 14);
126 return h ^ h >>> 16;
127 }
128
129
130
131
132
133
134
135 Segment<K, V> segmentFor(int hash) {
136 return segments[hash >>> segmentShift & segmentMask];
137 }
138
139 private static int hashOf(Object key) {
140 return hash(System.identityHashCode(key));
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155 static final class HashEntry<K, V> {
156 final Object key;
157 final int hash;
158 volatile Object value;
159 final HashEntry<K, V> next;
160
161 HashEntry(
162 K key, int hash, HashEntry<K, V> next, V value) {
163 this.hash = hash;
164 this.next = next;
165 this.key = key;
166 this.value = value;
167 }
168
169 @SuppressWarnings("unchecked")
170 K key() {
171 return (K) key;
172 }
173
174 @SuppressWarnings("unchecked")
175 V value() {
176 return (V) value;
177 }
178
179 void setValue(V value) {
180 this.value = value;
181 }
182
183 @SuppressWarnings("unchecked")
184 static <K, V> HashEntry<K, V>[] newArray(int i) {
185 return new HashEntry[i];
186 }
187 }
188
189
190
191
192
193
194 static final class Segment<K, V> extends ReentrantLock {
195
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 private static final long serialVersionUID = 5207829234977119743L;
231
232
233
234
235 transient volatile int count;
236
237
238
239
240
241
242
243
244 int modCount;
245
246
247
248
249
250 int threshold;
251
252
253
254
255 transient volatile HashEntry<K, V>[] table;
256
257
258
259
260
261
262 final float loadFactor;
263
264 Segment(int initialCapacity, float lf) {
265 loadFactor = lf;
266 setTable(HashEntry.<K, V>newArray(initialCapacity));
267 }
268
269 @SuppressWarnings("unchecked")
270 static <K, V> Segment<K, V>[] newArray(int i) {
271 return new Segment[i];
272 }
273
274 private static boolean keyEq(Object src, Object dest) {
275 return src == dest;
276 }
277
278
279
280
281
282 void setTable(HashEntry<K, V>[] newTable) {
283 threshold = (int) (newTable.length * loadFactor);
284 table = newTable;
285 }
286
287
288
289
290 HashEntry<K, V> getFirst(int hash) {
291 HashEntry<K, V>[] tab = table;
292 return tab[hash & tab.length - 1];
293 }
294
295 HashEntry<K, V> newHashEntry(
296 K key, int hash, HashEntry<K, V> next, V value) {
297 return new HashEntry<K, V>(key, hash, next, value);
298 }
299
300
301
302
303
304
305
306 V readValueUnderLock(HashEntry<K, V> e) {
307 lock();
308 try {
309 return e.value();
310 } finally {
311 unlock();
312 }
313 }
314
315
316
317 V get(Object key, int hash) {
318 if (count != 0) {
319 HashEntry<K, V>[] tab = table;
320 HashEntry<K, V> e = tab[hash & tab.length - 1];
321 if (tab != table) {
322 return get(key, hash);
323 }
324 while (e != null) {
325 if (e.hash == hash && keyEq(key, e.key())) {
326 V opaque = e.value();
327 if (opaque != null) {
328 return opaque;
329 }
330
331 return readValueUnderLock(e);
332 }
333 e = e.next;
334 }
335 }
336 return null;
337 }
338
339 boolean containsKey(Object key, int hash) {
340 if (count != 0) {
341 HashEntry<K, V>[] tab = table;
342 HashEntry<K, V> e = tab[hash & tab.length - 1];
343 if (tab != table) {
344 return containsKey(key, hash);
345 }
346 while (e != null) {
347 if (e.hash == hash && keyEq(key, e.key())) {
348 return true;
349 }
350 e = e.next;
351 }
352 }
353 return false;
354 }
355
356 boolean containsValue(Object value) {
357 if (count != 0) {
358 HashEntry<K, V>[] tab = table;
359 for (HashEntry<K, V> e: tab) {
360 for (; e != null; e = e.next) {
361 V opaque = e.value();
362 V v;
363
364 if (opaque == null) {
365 v = readValueUnderLock(e);
366 } else {
367 v = opaque;
368 }
369
370 if (value.equals(v)) {
371 return true;
372 }
373 }
374 }
375 if (table != tab) {
376 return containsValue(value);
377 }
378 }
379 return false;
380 }
381
382 boolean replace(K key, int hash, V oldValue, V newValue) {
383 lock();
384 try {
385 HashEntry<K, V> e = getFirst(hash);
386 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
387 e = e.next;
388 }
389
390 boolean replaced = false;
391 if (e != null && oldValue.equals(e.value())) {
392 replaced = true;
393 e.setValue(newValue);
394 }
395 return replaced;
396 } finally {
397 unlock();
398 }
399 }
400
401 V replace(K key, int hash, V newValue) {
402 lock();
403 try {
404 HashEntry<K, V> e = getFirst(hash);
405 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
406 e = e.next;
407 }
408
409 V oldValue = null;
410 if (e != null) {
411 oldValue = e.value();
412 e.setValue(newValue);
413 }
414 return oldValue;
415 } finally {
416 unlock();
417 }
418 }
419
420 V put(K key, int hash, V value, boolean onlyIfAbsent) {
421 lock();
422 try {
423 int c = count;
424 if (c ++ > threshold) {
425 int reduced = rehash();
426 if (reduced > 0) {
427 count = (c -= reduced) - 1;
428 }
429 }
430
431 HashEntry<K, V>[] tab = table;
432 int index = hash & tab.length - 1;
433 HashEntry<K, V> first = tab[index];
434 HashEntry<K, V> e = first;
435 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
436 e = e.next;
437 }
438
439 V oldValue;
440 if (e != null) {
441 oldValue = e.value();
442 if (!onlyIfAbsent) {
443 e.setValue(value);
444 }
445 } else {
446 oldValue = null;
447 ++ modCount;
448 tab[index] = newHashEntry(key, hash, first, value);
449 count = c;
450 }
451 return oldValue;
452 } finally {
453 unlock();
454 }
455 }
456
457 int rehash() {
458 HashEntry<K, V>[] oldTable = table;
459 int oldCapacity = oldTable.length;
460 if (oldCapacity >= MAXIMUM_CAPACITY) {
461 return 0;
462 }
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477 HashEntry<K, V>[] newTable = HashEntry.newArray(oldCapacity << 1);
478 threshold = (int) (newTable.length * loadFactor);
479 int sizeMask = newTable.length - 1;
480 int reduce = 0;
481 for (HashEntry<K, V> e: oldTable) {
482
483
484 if (e != null) {
485 HashEntry<K, V> next = e.next;
486 int idx = e.hash & sizeMask;
487
488
489 if (next == null) {
490 newTable[idx] = e;
491 } else {
492
493 HashEntry<K, V> lastRun = e;
494 int lastIdx = idx;
495 for (HashEntry<K, V> last = next; last != null; last = last.next) {
496 int k = last.hash & sizeMask;
497 if (k != lastIdx) {
498 lastIdx = k;
499 lastRun = last;
500 }
501 }
502 newTable[lastIdx] = lastRun;
503
504 for (HashEntry<K, V> p = e; p != lastRun; p = p.next) {
505
506 K key = p.key();
507 if (key == null) {
508 reduce++;
509 continue;
510 }
511 int k = p.hash & sizeMask;
512 HashEntry<K, V> n = newTable[k];
513 newTable[k] = newHashEntry(key, p.hash, n, p.value());
514 }
515 }
516 }
517 }
518 table = newTable;
519 Arrays.fill(oldTable, null);
520 return reduce;
521 }
522
523
524
525
526 V remove(Object key, int hash, Object value, boolean refRemove) {
527 lock();
528 try {
529 int c = count - 1;
530 HashEntry<K, V>[] tab = table;
531 int index = hash & tab.length - 1;
532 HashEntry<K, V> first = tab[index];
533 HashEntry<K, V> e = first;
534
535 while (e != null && key != e.key &&
536 (refRemove || hash != e.hash || !keyEq(key, e.key()))) {
537 e = e.next;
538 }
539
540 V oldValue = null;
541 if (e != null) {
542 V v = e.value();
543 if (value == null || value.equals(v)) {
544 oldValue = v;
545
546
547 ++ modCount;
548 HashEntry<K, V> newFirst = e.next;
549 for (HashEntry<K, V> p = first; p != e; p = p.next) {
550 K pKey = p.key();
551 if (pKey == null) {
552 c --;
553 continue;
554 }
555
556 newFirst = newHashEntry(
557 pKey, p.hash, newFirst, p.value());
558 }
559 tab[index] = newFirst;
560 count = c;
561 }
562 }
563 return oldValue;
564 } finally {
565 unlock();
566 }
567 }
568
569 void clear() {
570 if (count != 0) {
571 lock();
572 try {
573 HashEntry<K, V>[] tab = table;
574 for (int i = 0; i < tab.length; i ++) {
575 tab[i] = null;
576 }
577 ++ modCount;
578 count = 0;
579 } finally {
580 unlock();
581 }
582 }
583 }
584 }
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604 public ConcurrentIdentityHashMap(
605 int initialCapacity, float loadFactor,
606 int concurrencyLevel) {
607 if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) {
608 throw new IllegalArgumentException();
609 }
610
611 if (concurrencyLevel > MAX_SEGMENTS) {
612 concurrencyLevel = MAX_SEGMENTS;
613 }
614
615
616 int sshift = 0;
617 int ssize = 1;
618 while (ssize < concurrencyLevel) {
619 ++ sshift;
620 ssize <<= 1;
621 }
622 segmentShift = 32 - sshift;
623 segmentMask = ssize - 1;
624 segments = Segment.newArray(ssize);
625
626 if (initialCapacity > MAXIMUM_CAPACITY) {
627 initialCapacity = MAXIMUM_CAPACITY;
628 }
629 int c = initialCapacity / ssize;
630 if (c * ssize < initialCapacity) {
631 ++ c;
632 }
633 int cap = 1;
634 while (cap < c) {
635 cap <<= 1;
636 }
637
638 for (int i = 0; i < segments.length; ++ i) {
639 segments[i] = new Segment<K, V>(cap, loadFactor);
640 }
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
1226 public SimpleEntry(Entry<? extends K, ? extends V> entry) {
1227 key = entry.getKey();
1228 value = entry.getValue();
1229
1230 }
1231
1232 public K getKey() {
1233 return key;
1234 }
1235
1236 public V getValue() {
1237 return value;
1238 }
1239
1240 public V setValue(V value) {
1241 V oldValue = this.value;
1242 this.value = value;
1243 return oldValue;
1244 }
1245
1246 @Override
1247 public boolean equals(Object o) {
1248 if (!(o instanceof Map.Entry<?, ?>)) {
1249 return false;
1250 }
1251 @SuppressWarnings("rawtypes")
1252 Map.Entry e = (Map.Entry) o;
1253 return eq(key, e.getKey()) && eq(value, e.getValue());
1254 }
1255
1256 @Override
1257 public int hashCode() {
1258 return (key == null? 0 : key.hashCode()) ^ (value == null? 0 : value.hashCode());
1259 }
1260
1261 @Override
1262 public String toString() {
1263 return key + "=" + value;
1264 }
1265
1266 private static boolean eq(Object o1, Object o2) {
1267 return o1 == null? o2 == null : o1.equals(o2);
1268 }
1269 }
1270
1271
1272
1273
1274
1275 final class WriteThroughEntry extends SimpleEntry<K, V> {
1276
1277 WriteThroughEntry(K k, V v) {
1278 super(k, v);
1279 }
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289 @Override
1290 public V setValue(V value) {
1291
1292 if (value == null) {
1293 throw new NullPointerException();
1294 }
1295 V v = super.setValue(value);
1296 put(getKey(), value);
1297 return v;
1298 }
1299
1300 }
1301
1302 final class EntryIterator extends HashIterator implements
1303 ReusableIterator<Entry<K, V>> {
1304 public Map.Entry<K, V> next() {
1305 HashEntry<K, V> e = nextEntry();
1306 return new WriteThroughEntry(e.key(), e.value());
1307 }
1308 }
1309
1310 final class KeySet extends AbstractSet<K> {
1311 @Override
1312 public Iterator<K> iterator() {
1313
1314 return new KeyIterator();
1315 }
1316
1317 @Override
1318 public int size() {
1319 return ConcurrentIdentityHashMap.this.size();
1320 }
1321
1322 @Override
1323 public boolean isEmpty() {
1324 return ConcurrentIdentityHashMap.this.isEmpty();
1325 }
1326
1327 @Override
1328 public boolean contains(Object o) {
1329 return containsKey(o);
1330 }
1331
1332 @Override
1333 public boolean remove(Object o) {
1334 return ConcurrentIdentityHashMap.this.remove(o) != null;
1335
1336 }
1337
1338 @Override
1339 public void clear() {
1340 ConcurrentIdentityHashMap.this.clear();
1341 }
1342 }
1343
1344 final class Values extends AbstractCollection<V> {
1345 @Override
1346 public Iterator<V> iterator() {
1347 return new ValueIterator();
1348 }
1349
1350 @Override
1351 public int size() {
1352 return ConcurrentIdentityHashMap.this.size();
1353 }
1354
1355 @Override
1356 public boolean isEmpty() {
1357 return ConcurrentIdentityHashMap.this.isEmpty();
1358 }
1359
1360 @Override
1361 public boolean contains(Object o) {
1362 return containsValue(o);
1363 }
1364
1365 @Override
1366 public void clear() {
1367 ConcurrentIdentityHashMap.this.clear();
1368 }
1369 }
1370
1371 final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
1372 @Override
1373 public Iterator<Map.Entry<K, V>> iterator() {
1374 return new EntryIterator();
1375 }
1376
1377 @Override
1378 public boolean contains(Object o) {
1379 if (!(o instanceof Map.Entry<?, ?>)) {
1380 return false;
1381 }
1382 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1383 V v = get(e.getKey());
1384 return v != null && v.equals(e.getValue());
1385 }
1386
1387 @Override
1388 public boolean remove(Object o) {
1389 if (!(o instanceof Map.Entry<?, ?>)) {
1390 return false;
1391 }
1392 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1393 return ConcurrentIdentityHashMap.this.remove(e.getKey(), e.getValue());
1394 }
1395
1396 @Override
1397 public int size() {
1398 return ConcurrentIdentityHashMap.this.size();
1399 }
1400
1401 @Override
1402 public boolean isEmpty() {
1403 return ConcurrentIdentityHashMap.this.isEmpty();
1404 }
1405
1406 @Override
1407 public void clear() {
1408 ConcurrentIdentityHashMap.this.clear();
1409 }
1410 }
1411 }