View Javadoc

1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  /*
17   * Written by Doug Lea with assistance from members of JCP JSR-166
18   * Expert Group and released to the public domain, as explained at
19   * http://creativecommons.org/licenses/publicdomain
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   * An alternative weak-key {@link ConcurrentMap} which is similar to
43   * {@link java.util.concurrent.ConcurrentHashMap}.
44   * @param <K> the type of keys maintained by this map
45   * @param <V> the type of mapped values
46   */
47  public final class ConcurrentWeakKeyHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> {
48  
49      /*
50       * The basic strategy is to subdivide the table among Segments,
51       * each of which itself is a concurrently readable hash table.
52       */
53  
54      /**
55       * The default initial capacity for this table, used when not otherwise
56       * specified in a constructor.
57       */
58      static final int DEFAULT_INITIAL_CAPACITY = 16;
59  
60      /**
61       * The default load factor for this table, used when not otherwise specified
62       * in a constructor.
63       */
64      static final float DEFAULT_LOAD_FACTOR = 0.75f;
65  
66      /**
67       * The default concurrency level for this table, used when not otherwise
68       * specified in a constructor.
69       */
70      static final int DEFAULT_CONCURRENCY_LEVEL = 16;
71  
72      /**
73       * The maximum capacity, used if a higher value is implicitly specified by
74       * either of the constructors with arguments.  MUST be a power of two
75       * &lt;= 1&lt;&lt;30 to ensure that entries are indexable using integers.
76       */
77      static final int MAXIMUM_CAPACITY = 1 << 30;
78  
79      /**
80       * The maximum number of segments to allow; used to bound constructor
81       * arguments.
82       */
83      static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
84  
85      /**
86       * Number of unsynchronized retries in size and containsValue methods before
87       * resorting to locking. This is used to avoid unbounded retries if tables
88       * undergo continuous modification which would make it impossible to obtain
89       * an accurate result.
90       */
91      static final int RETRIES_BEFORE_LOCK = 2;
92  
93      /* ---------------- Fields -------------- */
94  
95      /**
96       * Mask value for indexing into segments. The upper bits of a key's hash
97       * code are used to choose the segment.
98       */
99      final int segmentMask;
100 
101     /**
102      * Shift value for indexing within segments.
103      */
104     final int segmentShift;
105 
106     /**
107      * The segments, each of which is a specialized hash table
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     /* ---------------- Small Utilities -------------- */
116 
117     /**
118      * Applies a supplemental hash function to a given hashCode, which defends
119      * against poor quality hash functions.  This is critical because
120      * ConcurrentReferenceHashMap uses power-of-two length hash tables, that
121      * otherwise encounter collisions for hashCodes that do not differ in lower
122      * or upper bits.
123      */
124     private static int hash(int h) {
125         // Spread bits to regularize both segment and index locations,
126         // using variant of single-word Wang/Jenkins hash.
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      * Returns the segment that should be used for key with given hash.
137      *
138      * @param hash the hash code for the key
139      * @return the segment
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     /* ---------------- Inner Classes -------------- */
150 
151     /**
152      * A weak-key reference which stores the key hash needed for reclamation.
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      * ConcurrentReferenceHashMap list entry. Note that this is never exported
174      * out as a user-visible Map.Entry.
175      *
176      * Because the value field is volatile, not final, it is legal wrt
177      * the Java Memory Model for an unsynchronized reader to see null
178      * instead of initial value when read via a data race.  Although a
179      * reordering leading to this is not likely to ever actually
180      * occur, the Segment.readValueUnderLock method is used as a
181      * backup in case a null (pre-initialized) value is ever seen in
182      * an unsynchronized access method.
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             keyRef = new WeakKeyReference<K>(key, hash, refQueue);
196             valueRef = value;
197         }
198 
199         @SuppressWarnings("unchecked")
200         K key() {
201             return ((Reference<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             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      * Segments are specialized versions of hash tables.  This subclasses from
229      * ReentrantLock opportunistically, just to simplify some locking and avoid
230      * separate construction.
231      */
232     static final class Segment<K, V> extends ReentrantLock {
233         /*
234          * Segments maintain a table of entry lists that are ALWAYS kept in a
235          * consistent state, so can be read without locking. Next fields of
236          * nodes are immutable (final).  All list additions are performed at the
237          * front of each bin. This makes it easy to check changes, and also fast
238          * to traverse. When nodes would otherwise be changed, new nodes are
239          * created to replace them. This works well for hash tables since the
240          * bin lists tend to be short. (The average length is less than two for
241          * the default load factor threshold.)
242          *
243          * Read operations can thus proceed without locking, but rely on
244          * selected uses of volatiles to ensure that completed write operations
245          * performed by other threads are noticed. For most purposes, the
246          * "count" field, tracking the number of elements, serves as that
247          * volatile variable ensuring visibility.  This is convenient because
248          * this field needs to be read in many read operations anyway:
249          *
250          *   - All (unsynchronized) read operations must first read the
251          *     "count" field, and should not look at table entries if
252          *     it is 0.
253          *
254          *   - All (synchronized) write operations should write to
255          *     the "count" field after structurally changing any bin.
256          *     The operations must not take any action that could even
257          *     momentarily cause a concurrent read operation to see
258          *     inconsistent data. This is made easier by the nature of
259          *     the read operations in Map. For example, no operation
260          *     can reveal that the table has grown but the threshold
261          *     has not yet been updated, so there are no atomicity
262          *     requirements for this with respect to reads.
263          *
264          * As a guide, all critical volatile reads and writes to the count field
265          * are marked in code comments.
266          */
267 
268         private static final long serialVersionUID = -8328104880676891126L;
269 
270         /**
271          * The number of elements in this segment's region.
272          */
273         transient volatile int count;
274 
275         /**
276          * Number of updates that alter the size of the table. This is used
277          * during bulk-read methods to make sure they see a consistent snapshot:
278          * If modCounts change during a traversal of segments computing size or
279          * checking containsValue, then we might have an inconsistent view of
280          * state so (usually) must retry.
281          */
282         int modCount;
283 
284         /**
285          * The table is rehashed when its size exceeds this threshold.
286          * (The value of this field is always <tt>(capacity * loadFactor)</tt>.)
287          */
288         int threshold;
289 
290         /**
291          * The per-segment table.
292          */
293         transient volatile HashEntry<K, V>[] table;
294 
295         /**
296          * The load factor for the hash table.  Even though this value is same
297          * for all segments, it is replicated to avoid needing links to outer
298          * object.
299          */
300         final float loadFactor;
301 
302         /**
303          * The collected weak-key reference queue for this segment. This should
304          * be (re)initialized whenever table is assigned,
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          * Sets table to new HashEntry array. Call only while holding lock or in
324          * constructor.
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          * Returns properly casted first entry of bin for given hash.
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          * Reads value field of an entry under lock. Called if value field ever
348          * appears to be null. This is possible only if a compiler happens to
349          * reorder a HashEntry initialization with its table assignment, which
350          * is legal under memory model but is not known to ever occur.
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         /* Specialized implementations of map methods */
363 
364         V get(Object key, int hash) {
365             if (count != 0) { // read-volatile
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); // recheck
375                     }
376                     e = e.next;
377                 }
378             }
379             return null;
380         }
381 
382         boolean containsKey(Object key, int hash) {
383             if (count != 0) { // read-volatile
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) { // read-volatile
397                 for (HashEntry<K, V> e: table) {
398                     for (; e != null; e = e.next) {
399                         Object opaque = e.valueRef;
400                         V v;
401 
402                         if (opaque == null) {
403                             v = readValueUnderLock(e); // recheck
404                         } else {
405                             v = e.dereferenceValue(opaque);
406                         }
407 
408                         if (value.equals(v)) {
409                             return true;
410                         }
411                     }
412                 }
413             }
414             return false;
415         }
416 
417         boolean replace(K key, int hash, V oldValue, V newValue) {
418             lock();
419             try {
420                 removeStale();
421                 HashEntry<K, V> e = getFirst(hash);
422                 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
423                     e = e.next;
424                 }
425 
426                 boolean replaced = false;
427                 if (e != null && oldValue.equals(e.value())) {
428                     replaced = true;
429                     e.setValue(newValue);
430                 }
431                 return replaced;
432             } finally {
433                 unlock();
434             }
435         }
436 
437         V replace(K key, int hash, V newValue) {
438             lock();
439             try {
440                 removeStale();
441                 HashEntry<K, V> e = getFirst(hash);
442                 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
443                     e = e.next;
444                 }
445 
446                 V oldValue = null;
447                 if (e != null) {
448                     oldValue = e.value();
449                     e.setValue(newValue);
450                 }
451                 return oldValue;
452             } finally {
453                 unlock();
454             }
455         }
456 
457         V put(K key, int hash, V value, boolean onlyIfAbsent) {
458             lock();
459             try {
460                 removeStale();
461                 int c = count;
462                 if (c ++ > threshold) { // ensure capacity
463                     int reduced = rehash();
464                     if (reduced > 0) {
465                         count = (c -= reduced) - 1; // write-volatile
466                     }
467                 }
468 
469                 HashEntry<K, V>[] tab = table;
470                 int index = hash & tab.length - 1;
471                 HashEntry<K, V> first = tab[index];
472                 HashEntry<K, V> e = first;
473                 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
474                     e = e.next;
475                 }
476 
477                 V oldValue;
478                 if (e != null) {
479                     oldValue = e.value();
480                     if (!onlyIfAbsent) {
481                         e.setValue(value);
482                     }
483                 } else {
484                     oldValue = null;
485                     ++ modCount;
486                     tab[index] = newHashEntry(key, hash, first, value);
487                     count = c; // write-volatile
488                 }
489                 return oldValue;
490             } finally {
491                 unlock();
492             }
493         }
494 
495         int rehash() {
496             HashEntry<K, V>[] oldTable = table;
497             int oldCapacity = oldTable.length;
498             if (oldCapacity >= MAXIMUM_CAPACITY) {
499                 return 0;
500             }
501 
502             /*
503              * Reclassify nodes in each list to new Map.  Because we are using
504              * power-of-two expansion, the elements from each bin must either
505              * stay at same index, or move with a power of two offset. We
506              * eliminate unnecessary node creation by catching cases where old
507              * nodes can be reused because their next fields won't change.
508              * Statistically, at the default threshold, only about one-sixth of
509              * them need cloning when a table doubles. The nodes they replace
510              * will be garbage collectable as soon as they are no longer
511              * referenced by any reader thread that may be in the midst of
512              * traversing table right now.
513              */
514 
515             HashEntry<K, V>[] newTable = HashEntry.newArray(oldCapacity << 1);
516             threshold = (int) (newTable.length * loadFactor);
517             int sizeMask = newTable.length - 1;
518             int reduce = 0;
519             for (HashEntry<K, V> e: oldTable) {
520                 // We need to guarantee that any existing reads of old Map can
521                 // proceed. So we cannot yet null out each bin.
522                 if (e != null) {
523                     HashEntry<K, V> next = e.next;
524                     int idx = e.hash & sizeMask;
525 
526                     // Single node on list
527                     if (next == null) {
528                         newTable[idx] = e;
529                     } else {
530                         // Reuse trailing consecutive sequence at same slot
531                         HashEntry<K, V> lastRun = e;
532                         int lastIdx = idx;
533                         for (HashEntry<K, V> last = next; last != null; last = last.next) {
534                             int k = last.hash & sizeMask;
535                             if (k != lastIdx) {
536                                 lastIdx = k;
537                                 lastRun = last;
538                             }
539                         }
540                         newTable[lastIdx] = lastRun;
541                         // Clone all remaining nodes
542                         for (HashEntry<K, V> p = e; p != lastRun; p = p.next) {
543                             // Skip GC'd weak references
544                             K key = p.key();
545                             if (key == null) {
546                                 reduce++;
547                                 continue;
548                             }
549                             int k = p.hash & sizeMask;
550                             HashEntry<K, V> n = newTable[k];
551                             newTable[k] = newHashEntry(key, p.hash, n, p.value());
552                         }
553                     }
554                 }
555             }
556             table = newTable;
557             return reduce;
558         }
559 
560         /**
561          * Remove; match on key only if value null, else match both.
562          */
563         V remove(Object key, int hash, Object value, boolean refRemove) {
564             lock();
565             try {
566                 if (!refRemove) {
567                     removeStale();
568                 }
569                 int c = count - 1;
570                 HashEntry<K, V>[] tab = table;
571                 int index = hash & tab.length - 1;
572                 HashEntry<K, V> first = tab[index];
573                 HashEntry<K, V> e = first;
574                 // a reference remove operation compares the Reference instance
575                 while (e != null && key != e.keyRef &&
576                         (refRemove || hash != e.hash || !keyEq(key, e.key()))) {
577                     e = e.next;
578                 }
579 
580                 V oldValue = null;
581                 if (e != null) {
582                     V v = e.value();
583                     if (value == null || value.equals(v)) {
584                         oldValue = v;
585                         // All entries following removed node can stay in list,
586                         // but all preceding ones need to be cloned.
587                         ++ modCount;
588                         HashEntry<K, V> newFirst = e.next;
589                         for (HashEntry<K, V> p = first; p != e; p = p.next) {
590                             K pKey = p.key();
591                             if (pKey == null) { // Skip GC'd keys
592                                 c --;
593                                 continue;
594                             }
595 
596                             newFirst = newHashEntry(
597                                     pKey, p.hash, newFirst, p.value());
598                         }
599                         tab[index] = newFirst;
600                         count = c; // write-volatile
601                     }
602                 }
603                 return oldValue;
604             } finally {
605                 unlock();
606             }
607         }
608 
609         @SuppressWarnings("rawtypes")
610         void removeStale() {
611             WeakKeyReference ref;
612             while ((ref = (WeakKeyReference) refQueue.poll()) != null) {
613                 remove(ref.keyRef(), ref.keyHash(), null, true);
614             }
615         }
616 
617         void clear() {
618             if (count != 0) {
619                 lock();
620                 try {
621                     HashEntry<K, V>[] tab = table;
622                     for (int i = 0; i < tab.length; i ++) {
623                         tab[i] = null;
624                     }
625                     ++ modCount;
626                     // replace the reference queue to avoid unnecessary stale
627                     // cleanups
628                     refQueue = new ReferenceQueue<Object>();
629                     count = 0; // write-volatile
630                 } finally {
631                     unlock();
632                 }
633             }
634         }
635     }
636 
637     /* ---------------- Public operations -------------- */
638 
639     /**
640      * Creates a new, empty map with the specified initial capacity, load factor
641      * and concurrency level.
642      *
643      * @param initialCapacity the initial capacity. The implementation performs
644      *                        internal sizing to accommodate this many elements.
645      * @param loadFactor the load factor threshold, used to control resizing.
646      *                   Resizing may be performed when the average number of
647      *                   elements per bin exceeds this threshold.
648      * @param concurrencyLevel the estimated number of concurrently updating
649      *                         threads. The implementation performs internal
650      *                         sizing to try to accommodate this many threads.
651      * @throws IllegalArgumentException if the initial capacity is negative or
652      *                                  the load factor or concurrencyLevel are
653      *                                  nonpositive.
654      */
655     public ConcurrentWeakKeyHashMap(
656             int initialCapacity, float loadFactor, int concurrencyLevel) {
657         if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) {
658             throw new IllegalArgumentException();
659         }
660 
661         if (concurrencyLevel > MAX_SEGMENTS) {
662             concurrencyLevel = MAX_SEGMENTS;
663         }
664 
665         // Find power-of-two sizes best matching arguments
666         int sshift = 0;
667         int ssize = 1;
668         while (ssize < concurrencyLevel) {
669             ++ sshift;
670             ssize <<= 1;
671         }
672         segmentShift = 32 - sshift;
673         segmentMask = ssize - 1;
674         segments = Segment.newArray(ssize);
675 
676         if (initialCapacity > MAXIMUM_CAPACITY) {
677             initialCapacity = MAXIMUM_CAPACITY;
678         }
679         int c = initialCapacity / ssize;
680         if (c * ssize < initialCapacity) {
681             ++ c;
682         }
683         int cap = 1;
684         while (cap < c) {
685             cap <<= 1;
686         }
687 
688         for (int i = 0; i < segments.length; ++ i) {
689             segments[i] = new Segment<K, V>(cap, loadFactor);
690         }
691     }
692 
693     /**
694      * Creates a new, empty map with the specified initial capacity and load
695      * factor and with the default reference types (weak keys, strong values),
696      * and concurrencyLevel (16).
697      *
698      * @param initialCapacity The implementation performs internal sizing to
699      *                        accommodate this many elements.
700      * @param loadFactor the load factor threshold, used to control resizing.
701      *                   Resizing may be performed when the average number of
702      *                   elements per bin exceeds this threshold.
703      * @throws IllegalArgumentException if the initial capacity of elements is
704      *                                  negative or the load factor is
705      *                                  nonpositive
706      */
707     public ConcurrentWeakKeyHashMap(int initialCapacity, float loadFactor) {
708         this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
709     }
710 
711     /**
712      * Creates a new, empty map with the specified initial capacity, and with
713      * default reference types (weak keys, strong values), load factor (0.75)
714      * and concurrencyLevel (16).
715      *
716      * @param initialCapacity the initial capacity. The implementation performs
717      *                        internal sizing to accommodate this many elements.
718      * @throws IllegalArgumentException if the initial capacity of elements is
719      *                                  negative.
720      */
721     public ConcurrentWeakKeyHashMap(int initialCapacity) {
722         this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
723     }
724 
725     /**
726      * Creates a new, empty map with a default initial capacity (16), reference
727      * types (weak keys, strong values), default load factor (0.75) and
728      * concurrencyLevel (16).
729      */
730     public ConcurrentWeakKeyHashMap() {
731         this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
732     }
733 
734     /**
735      * Creates a new map with the same mappings as the given map. The map is
736      * created with a capacity of 1.5 times the number of mappings in the given
737      * map or 16 (whichever is greater), and a default load factor (0.75) and
738      * concurrencyLevel (16).
739      *
740      * @param m the map
741      */
742     public ConcurrentWeakKeyHashMap(Map<? extends K, ? extends V> m) {
743         this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
744              DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR,
745              DEFAULT_CONCURRENCY_LEVEL);
746         putAll(m);
747     }
748 
749     /**
750      * Returns <tt>true</tt> if this map contains no key-value mappings.
751      *
752      * @return <tt>true</tt> if this map contains no key-value mappings
753      */
754     @Override
755     public boolean isEmpty() {
756         final Segment<K, V>[] segments = this.segments;
757         /*
758          * We keep track of per-segment modCounts to avoid ABA problems in which
759          * an element in one segment was added and in another removed during
760          * traversal, in which case the table was never actually empty at any
761          * point. Note the similar use of modCounts in the size() and
762          * containsValue() methods, which are the only other methods also
763          * susceptible to ABA problems.
764          */
765         int[] mc = new int[segments.length];
766         int mcsum = 0;
767         for (int i = 0; i < segments.length; ++ i) {
768             if (segments[i].count != 0) {
769                 return false;
770             } else {
771                 mcsum += mc[i] = segments[i].modCount;
772             }
773         }
774         // If mcsum happens to be zero, then we know we got a snapshot before
775         // any modifications at all were made.  This is probably common enough
776         // to bother tracking.
777         if (mcsum != 0) {
778             for (int i = 0; i < segments.length; ++ i) {
779                 if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
780                     return false;
781                 }
782             }
783         }
784         return true;
785     }
786 
787     /**
788      * Returns the number of key-value mappings in this map. If the map contains
789      * more than <tt>Integer.MAX_VALUE</tt> elements, returns
790      * <tt>Integer.MAX_VALUE</tt>.
791      *
792      * @return the number of key-value mappings in this map
793      */
794     @Override
795     public int size() {
796         final Segment<K, V>[] segments = this.segments;
797         long sum = 0;
798         long check = 0;
799         int[] mc = new int[segments.length];
800         // Try a few times to get accurate count. On failure due to continuous
801         // async changes in table, resort to locking.
802         for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
803             check = 0;
804             sum = 0;
805             int mcsum = 0;
806             for (int i = 0; i < segments.length; ++ i) {
807                 sum += segments[i].count;
808                 mcsum += mc[i] = segments[i].modCount;
809             }
810             if (mcsum != 0) {
811                 for (int i = 0; i < segments.length; ++ i) {
812                     check += segments[i].count;
813                     if (mc[i] != segments[i].modCount) {
814                         check = -1; // force retry
815                         break;
816                     }
817                 }
818             }
819             if (check == sum) {
820                 break;
821             }
822         }
823         if (check != sum) { // Resort to locking all segments
824             sum = 0;
825             for (Segment<K, V> segment: segments) {
826                 segment.lock();
827             }
828             for (Segment<K, V> segment: segments) {
829                 sum += segment.count;
830             }
831             for (Segment<K, V> segment: segments) {
832                 segment.unlock();
833             }
834         }
835         if (sum > Integer.MAX_VALUE) {
836             return Integer.MAX_VALUE;
837         } else {
838             return (int) sum;
839         }
840     }
841 
842     /**
843      * Returns the value to which the specified key is mapped, or {@code null}
844      * if this map contains no mapping for the key.
845      *
846      * <p>More formally, if this map contains a mapping from a key {@code k} to
847      * a value {@code v} such that {@code key.equals(k)}, then this method
848      * returns {@code v}; otherwise it returns {@code null}.  (There can be at
849      * most one such mapping.)
850      *
851      * @throws NullPointerException if the specified key is null
852      */
853     @Override
854     public V get(Object key) {
855         int hash = hashOf(key);
856         return segmentFor(hash).get(key, hash);
857     }
858 
859     /**
860      * Tests if the specified object is a key in this table.
861      *
862      * @param  key   possible key
863      * @return <tt>true</tt> if and only if the specified object is a key in
864      *         this table, as determined by the <tt>equals</tt> method;
865      *         <tt>false</tt> otherwise.
866      * @throws NullPointerException if the specified key is null
867      */
868     @Override
869     public boolean containsKey(Object key) {
870         int hash = hashOf(key);
871         return segmentFor(hash).containsKey(key, hash);
872     }
873 
874     /**
875      * Returns <tt>true</tt> if this map maps one or more keys to the specified
876      * value. Note: This method requires a full internal traversal of the hash
877      * table, and so is much slower than method <tt>containsKey</tt>.
878      *
879      * @param value value whose presence in this map is to be tested
880      * @return <tt>true</tt> if this map maps one or more keys to the specified
881      *         value
882      * @throws NullPointerException if the specified value is null
883      */
884 
885     @Override
886     public boolean containsValue(Object value) {
887         if (value == null) {
888             throw new NullPointerException();
889         }
890 
891         // See explanation of modCount use above
892 
893         final Segment<K, V>[] segments = this.segments;
894         int[] mc = new int[segments.length];
895 
896         // Try a few times without locking
897         for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
898             int mcsum = 0;
899             for (int i = 0; i < segments.length; ++ i) {
900                 mcsum += mc[i] = segments[i].modCount;
901                 if (segments[i].containsValue(value)) {
902                     return true;
903                 }
904             }
905             boolean cleanSweep = true;
906             if (mcsum != 0) {
907                 for (int i = 0; i < segments.length; ++ i) {
908                     if (mc[i] != segments[i].modCount) {
909                         cleanSweep = false;
910                         break;
911                     }
912                 }
913             }
914             if (cleanSweep) {
915                 return false;
916             }
917         }
918         // Resort to locking all segments
919         for (Segment<K, V> segment: segments) {
920             segment.lock();
921         }
922         boolean found = false;
923         try {
924             for (Segment<K, V> segment: segments) {
925                 if (segment.containsValue(value)) {
926                     found = true;
927                     break;
928                 }
929             }
930         } finally {
931             for (Segment<K, V> segment: segments) {
932                 segment.unlock();
933             }
934         }
935         return found;
936     }
937 
938     /**
939      * Legacy method testing if some key maps into the specified value in this
940      * table.  This method is identical in functionality to
941      * {@link #containsValue}, and exists solely to ensure full compatibility
942      * with class {@link Hashtable}, which supported this method prior to
943      * introduction of the Java Collections framework.
944      *
945      * @param  value a value to search for
946      * @return <tt>true</tt> if and only if some key maps to the <tt>value</tt>
947      *         argument in this table as determined by the <tt>equals</tt>
948      *         method; <tt>false</tt> otherwise
949      * @throws NullPointerException if the specified value is null
950      */
951     public boolean contains(Object value) {
952         return containsValue(value);
953     }
954 
955     /**
956      * Maps the specified key to the specified value in this table.  Neither the
957      * key nor the value can be null.
958      *
959      * <p>The value can be retrieved by calling the <tt>get</tt> method with a
960      * key that is equal to the original key.
961      *
962      * @param key key with which the specified value is to be associated
963      * @param value value to be associated with the specified key
964      * @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
965      *         if there was no mapping for <tt>key</tt>
966      * @throws NullPointerException if the specified key or value is null
967      */
968     @Override
969     public V put(K key, V value) {
970         if (value == null) {
971             throw new NullPointerException();
972         }
973         int hash = hashOf(key);
974         return segmentFor(hash).put(key, hash, value, false);
975     }
976 
977     /**
978      * @return the previous value associated with the specified key, or
979      *         <tt>null</tt> if there was no mapping for the key
980      * @throws NullPointerException if the specified key or value is null
981      */
982     public V putIfAbsent(K key, V value) {
983         if (value == null) {
984             throw new NullPointerException();
985         }
986         int hash = hashOf(key);
987         return segmentFor(hash).put(key, hash, value, true);
988     }
989 
990     /**
991      * Copies all of the mappings from the specified map to this one.  These
992      * mappings replace any mappings that this map had for any of the keys
993      * currently in the specified map.
994      *
995      * @param m mappings to be stored in this map
996      */
997     @Override
998     public void putAll(Map<? extends K, ? extends V> m) {
999         for (Map.Entry<? extends K, ? extends V> e: m.entrySet()) {
1000             put(e.getKey(), e.getValue());
1001         }
1002     }
1003 
1004     /**
1005      * Removes the key (and its corresponding value) from this map.  This method
1006      * does nothing if the key is not in the map.
1007      *
1008      * @param  key the key that needs to be removed
1009      * @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
1010      *         if there was no mapping for <tt>key</tt>
1011      * @throws NullPointerException if the specified key is null
1012      */
1013     @Override
1014     public V remove(Object key) {
1015         int hash = hashOf(key);
1016         return segmentFor(hash).remove(key, hash, null, false);
1017     }
1018 
1019     /**
1020      * @throws NullPointerException if the specified key is null
1021      */
1022     public boolean remove(Object key, Object value) {
1023         int hash = hashOf(key);
1024         if (value == null) {
1025             return false;
1026         }
1027         return segmentFor(hash).remove(key, hash, value, false) != null;
1028     }
1029 
1030     /**
1031      * @throws NullPointerException if any of the arguments are null
1032      */
1033     public boolean replace(K key, V oldValue, V newValue) {
1034         if (oldValue == null || newValue == null) {
1035             throw new NullPointerException();
1036         }
1037         int hash = hashOf(key);
1038         return segmentFor(hash).replace(key, hash, oldValue, newValue);
1039     }
1040 
1041     /**
1042      * @return the previous value associated with the specified key, or
1043      *         <tt>null</tt> if there was no mapping for the key
1044      * @throws NullPointerException if the specified key or value is null
1045      */
1046     public V replace(K key, V value) {
1047         if (value == null) {
1048             throw new NullPointerException();
1049         }
1050         int hash = hashOf(key);
1051         return segmentFor(hash).replace(key, hash, value);
1052     }
1053 
1054     /**
1055      * Removes all of the mappings from this map.
1056      */
1057     @Override
1058     public void clear() {
1059         for (Segment<K, V> segment: segments) {
1060             segment.clear();
1061         }
1062     }
1063 
1064     /**
1065      * Removes any stale entries whose keys have been finalized. Use of this
1066      * method is normally not necessary since stale entries are automatically
1067      * removed lazily, when blocking operations are required. However, there are
1068      * some cases where this operation should be performed eagerly, such as
1069      * cleaning up old references to a ClassLoader in a multi-classloader
1070      * environment.
1071      *
1072      * Note: this method will acquire locks, one at a time, across all segments
1073      * of this table, so if it is to be used, it should be used sparingly.
1074      */
1075     public void purgeStaleEntries() {
1076         for (Segment<K, V> segment: segments) {
1077             segment.removeStale();
1078         }
1079     }
1080 
1081     /**
1082      * Returns a {@link Set} view of the keys contained in this map.  The set is
1083      * backed by the map, so changes to the map are reflected in the set, and
1084      * vice-versa.  The set supports element removal, which removes the
1085      * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
1086      * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
1087      * <tt>clear</tt> operations.  It does not support the <tt>add</tt> or
1088      * <tt>addAll</tt> operations.
1089      *
1090      * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator that
1091      * will never throw {@link ConcurrentModificationException}, and guarantees
1092      * to traverse elements as they existed upon construction of the iterator,
1093      * and may (but is not guaranteed to) reflect any modifications subsequent
1094      * to construction.
1095      */
1096     @Override
1097     public Set<K> keySet() {
1098         Set<K> ks = keySet;
1099         return ks != null? ks : (keySet = new KeySet());
1100     }
1101 
1102     /**
1103      * Returns a {@link Collection} view of the values contained in this map.
1104      * The collection is backed by the map, so changes to the map are reflected
1105      * in the collection, and vice-versa.  The collection supports element
1106      * removal, which removes the corresponding mapping from this map, via the
1107      * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>, <tt>removeAll</tt>,
1108      * <tt>retainAll</tt>, and <tt>clear</tt> operations.  It does not support
1109      * the <tt>add</tt> or <tt>addAll</tt> operations.
1110      *
1111      * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator that
1112      * will never throw {@link ConcurrentModificationException}, and guarantees
1113      * to traverse elements as they existed upon construction of the iterator,
1114      * and may (but is not guaranteed to) reflect any modifications subsequent
1115      * to construction.
1116      */
1117     @Override
1118     public Collection<V> values() {
1119         Collection<V> vs = values;
1120         return vs != null? vs : (values = new Values());
1121     }
1122 
1123     /**
1124      * Returns a {@link Set} view of the mappings contained in this map.
1125      * The set is backed by the map, so changes to the map are reflected in the
1126      * set, and vice-versa.  The set supports element removal, which removes the
1127      * corresponding mapping from the map, via the <tt>Iterator.remove</tt>,
1128      * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
1129      * <tt>clear</tt> operations.  It does not support the <tt>add</tt> or
1130      * <tt>addAll</tt> operations.
1131      *
1132      * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator that
1133      * will never throw {@link ConcurrentModificationException}, and guarantees
1134      * to traverse elements as they existed upon construction of the iterator,
1135      * and may (but is not guaranteed to) reflect any modifications subsequent
1136      * to construction.
1137      */
1138     @Override
1139     public Set<Map.Entry<K, V>> entrySet() {
1140         Set<Map.Entry<K, V>> es = entrySet;
1141         return es != null? es : (entrySet = new EntrySet());
1142     }
1143 
1144     /**
1145      * Returns an enumeration of the keys in this table.
1146      *
1147      * @return an enumeration of the keys in this table
1148      * @see #keySet()
1149      */
1150     public Enumeration<K> keys() {
1151         return new KeyIterator();
1152     }
1153 
1154     /**
1155      * Returns an enumeration of the values in this table.
1156      *
1157      * @return an enumeration of the values in this table
1158      * @see #values()
1159      */
1160     public Enumeration<V> elements() {
1161         return new ValueIterator();
1162     }
1163 
1164     /* ---------------- Iterator Support -------------- */
1165 
1166     abstract class HashIterator {
1167         int nextSegmentIndex;
1168         int nextTableIndex;
1169         HashEntry<K, V>[] currentTable;
1170         HashEntry<K, V> nextEntry;
1171         HashEntry<K, V> lastReturned;
1172         K currentKey; // Strong reference to weak key (prevents gc)
1173 
1174         HashIterator() {
1175             nextSegmentIndex = segments.length - 1;
1176             nextTableIndex = -1;
1177             advance();
1178         }
1179 
1180         public void rewind() {
1181             nextSegmentIndex = segments.length - 1;
1182             nextTableIndex = -1;
1183             currentTable = null;
1184             nextEntry = null;
1185             lastReturned = null;
1186             currentKey = null;
1187             advance();
1188         }
1189 
1190         public boolean hasMoreElements() {
1191             return hasNext();
1192         }
1193 
1194         final void advance() {
1195             if (nextEntry != null && (nextEntry = nextEntry.next) != null) {
1196                 return;
1197             }
1198 
1199             while (nextTableIndex >= 0) {
1200                 if ((nextEntry = currentTable[nextTableIndex --]) != null) {
1201                     return;
1202                 }
1203             }
1204 
1205             while (nextSegmentIndex >= 0) {
1206                 Segment<K, V> seg = segments[nextSegmentIndex --];
1207                 if (seg.count != 0) {
1208                     currentTable = seg.table;
1209                     for (int j = currentTable.length - 1; j >= 0; -- j) {
1210                         if ((nextEntry = currentTable[j]) != null) {
1211                             nextTableIndex = j - 1;
1212                             return;
1213                         }
1214                     }
1215                 }
1216             }
1217         }
1218 
1219         public boolean hasNext() {
1220             while (nextEntry != null) {
1221                 if (nextEntry.key() != null) {
1222                     return true;
1223                 }
1224                 advance();
1225             }
1226 
1227             return false;
1228         }
1229 
1230         HashEntry<K, V> nextEntry() {
1231             do {
1232                 if (nextEntry == null) {
1233                     throw new NoSuchElementException();
1234                 }
1235 
1236                 lastReturned = nextEntry;
1237                 currentKey = lastReturned.key();
1238                 advance();
1239             } while (currentKey == null); // Skip GC'd keys
1240 
1241             return lastReturned;
1242         }
1243 
1244         public void remove() {
1245             if (lastReturned == null) {
1246                 throw new IllegalStateException();
1247             }
1248             ConcurrentWeakKeyHashMap.this.remove(currentKey);
1249             lastReturned = null;
1250         }
1251     }
1252 
1253     final class KeyIterator
1254             extends HashIterator implements ReusableIterator<K>, Enumeration<K> {
1255 
1256         public K next() {
1257             return nextEntry().key();
1258         }
1259 
1260         public K nextElement() {
1261             return nextEntry().key();
1262         }
1263     }
1264 
1265     final class ValueIterator
1266             extends HashIterator implements ReusableIterator<V>, Enumeration<V> {
1267 
1268         public V next() {
1269             return nextEntry().value();
1270         }
1271 
1272         public V nextElement() {
1273             return nextEntry().value();
1274         }
1275     }
1276 
1277     /*
1278      * This class is needed for JDK5 compatibility.
1279      */
1280     static class SimpleEntry<K, V> implements Entry<K, V> {
1281 
1282         private final K key;
1283 
1284         private V value;
1285 
1286         public SimpleEntry(K key, V value) {
1287             this.key = key;
1288             this.value = value;
1289 
1290         }
1291 
1292         public SimpleEntry(Entry<? extends K, ? extends V> entry) {
1293             key = entry.getKey();
1294             value = entry.getValue();
1295 
1296         }
1297 
1298         public K getKey() {
1299             return key;
1300         }
1301 
1302         public V getValue() {
1303             return value;
1304         }
1305 
1306         public V setValue(V value) {
1307             V oldValue = this.value;
1308             this.value = value;
1309             return oldValue;
1310         }
1311 
1312         @Override
1313         public boolean equals(Object o) {
1314             if (!(o instanceof Map.Entry<?, ?>)) {
1315                 return false;
1316             }
1317             @SuppressWarnings("rawtypes")
1318             Map.Entry e = (Map.Entry) o;
1319             return eq(key, e.getKey()) && eq(value, e.getValue());
1320         }
1321 
1322         @Override
1323         public int hashCode() {
1324             return (key == null? 0 : key.hashCode()) ^ (value == null? 0 : value.hashCode());
1325         }
1326 
1327         @Override
1328         public String toString() {
1329             return key + "=" + value;
1330         }
1331 
1332         private static boolean eq(Object o1, Object o2) {
1333             return o1 == null? o2 == null : o1.equals(o2);
1334         }
1335     }
1336 
1337     /**
1338      * Custom Entry class used by EntryIterator.next(), that relays setValue
1339      * changes to the underlying map.
1340      */
1341     final class WriteThroughEntry extends SimpleEntry<K, V> {
1342 
1343         WriteThroughEntry(K k, V v) {
1344             super(k, v);
1345         }
1346 
1347         /**
1348          * Set our entry's value and write through to the map. The value to
1349          * return is somewhat arbitrary here. Since a WriteThroughEntry does not
1350          * necessarily track asynchronous changes, the most recent "previous"
1351          * value could be different from what we return (or could even have been
1352          * removed in which case the put will re-establish). We do not and can
1353          * not guarantee more.
1354          */
1355         @Override
1356         public V setValue(V value) {
1357 
1358             if (value == null) {
1359                 throw new NullPointerException();
1360             }
1361             V v = super.setValue(value);
1362             put(getKey(), value);
1363             return v;
1364         }
1365 
1366     }
1367 
1368     final class EntryIterator extends HashIterator implements
1369             ReusableIterator<Entry<K, V>> {
1370         public Map.Entry<K, V> next() {
1371             HashEntry<K, V> e = nextEntry();
1372             return new WriteThroughEntry(e.key(), e.value());
1373         }
1374     }
1375 
1376     final class KeySet extends AbstractSet<K> {
1377         @Override
1378         public Iterator<K> iterator() {
1379 
1380             return new KeyIterator();
1381         }
1382 
1383         @Override
1384         public int size() {
1385             return ConcurrentWeakKeyHashMap.this.size();
1386         }
1387 
1388         @Override
1389         public boolean isEmpty() {
1390             return ConcurrentWeakKeyHashMap.this.isEmpty();
1391         }
1392 
1393         @Override
1394         public boolean contains(Object o) {
1395             return containsKey(o);
1396         }
1397 
1398         @Override
1399         public boolean remove(Object o) {
1400             return ConcurrentWeakKeyHashMap.this.remove(o) != null;
1401 
1402         }
1403 
1404         @Override
1405         public void clear() {
1406             ConcurrentWeakKeyHashMap.this.clear();
1407         }
1408     }
1409 
1410     final class Values extends AbstractCollection<V> {
1411         @Override
1412         public Iterator<V> iterator() {
1413             return new ValueIterator();
1414         }
1415 
1416         @Override
1417         public int size() {
1418             return ConcurrentWeakKeyHashMap.this.size();
1419         }
1420 
1421         @Override
1422         public boolean isEmpty() {
1423             return ConcurrentWeakKeyHashMap.this.isEmpty();
1424         }
1425 
1426         @Override
1427         public boolean contains(Object o) {
1428             return containsValue(o);
1429         }
1430 
1431         @Override
1432         public void clear() {
1433             ConcurrentWeakKeyHashMap.this.clear();
1434         }
1435     }
1436 
1437     final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
1438         @Override
1439         public Iterator<Map.Entry<K, V>> iterator() {
1440             return new EntryIterator();
1441         }
1442 
1443         @Override
1444         public boolean contains(Object o) {
1445             if (!(o instanceof Map.Entry<?, ?>)) {
1446                 return false;
1447             }
1448             Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1449             V v = get(e.getKey());
1450             return v != null && v.equals(e.getValue());
1451         }
1452 
1453         @Override
1454         public boolean remove(Object o) {
1455             if (!(o instanceof Map.Entry<?, ?>)) {
1456                 return false;
1457             }
1458             Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1459             return ConcurrentWeakKeyHashMap.this.remove(e.getKey(), e.getValue());
1460         }
1461 
1462         @Override
1463         public int size() {
1464             return ConcurrentWeakKeyHashMap.this.size();
1465         }
1466 
1467         @Override
1468         public boolean isEmpty() {
1469             return ConcurrentWeakKeyHashMap.this.isEmpty();
1470         }
1471 
1472         @Override
1473         public void clear() {
1474             ConcurrentWeakKeyHashMap.this.clear();
1475         }
1476     }
1477 }