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