• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import com.google.common.base.Function;
20 
21 import java.io.IOException;
22 import java.io.Serializable;
23 import java.lang.reflect.Array;
24 import java.lang.reflect.Field;
25 import java.util.AbstractCollection;
26 import java.util.AbstractMap;
27 import java.util.AbstractSet;
28 import java.util.Collection;
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.NoSuchElementException;
32 import java.util.Set;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ConcurrentMap;
35 import java.util.concurrent.atomic.AtomicReferenceArray;
36 import java.util.concurrent.locks.ReentrantLock;
37 
38 import javax.annotation.Nullable;
39 
40 /**
41  * A framework for concurrent hash map implementations. The
42  * CustomConcurrentHashMap class itself is not extensible and does not contain
43  * any methods. Use {@link Builder} to create a custom concurrent hash map
44  * instance. Client libraries implement {@link Strategy}, and this class
45  * provides the surrounding concurrent data structure which implements {@link
46  * ConcurrentMap}. Additionally supports implementing maps where {@link
47  * Map#get} atomically computes values on demand (see {@link
48  * Builder#buildComputingMap(CustomConcurrentHashMap.ComputingStrategy,
49  * Function)}).
50  *
51  * <p>The resulting hash table supports full concurrency of retrievals and
52  * adjustable expected concurrency for updates. Even though all operations are
53  * thread-safe, retrieval operations do <i>not</i> entail locking,
54  * and there is <i>not</i> any support for locking the entire table
55  * in a way that prevents all access.
56  *
57  * <p>Retrieval operations (including {@link Map#get}) generally do not
58  * block, so may overlap with update operations (including
59  * {@link Map#put} and {@link Map#remove}). Retrievals reflect the results
60  * of the most recently <i>completed</i> update operations holding
61  * upon their onset. For aggregate operations such as {@link Map#putAll}
62  * and {@link Map#clear}, concurrent retrievals may reflect insertion or
63  * removal of only some entries. Similarly, iterators return elements
64  * reflecting the state of the hash table at some point at or since the
65  * creation of the iterator. They do <i>not</i> throw
66  * {@link java.util.ConcurrentModificationException}. However, iterators can
67  * only be used by one thread at a time.
68  *
69  * <p>The resulting {@link ConcurrentMap} and its views and iterators implement
70  * all of the <i>optional</i> methods of the {@link java.util.Map} and {@link
71  * java.util.Iterator} interfaces. Partially reclaimed entries are never
72  * exposed through the views or iterators.
73  *
74  * <p>For example, the following strategy emulates the behavior of
75  * {@link java.util.concurrent.ConcurrentHashMap}:
76  *
77  * <pre> {@code
78  * class ConcurrentHashMapStrategy<K, V>
79  *     implements CustomConcurrentHashMap.Strategy<K, V,
80  *     InternalEntry<K, V>>, Serializable {
81  *   public InternalEntry<K, V> newEntry(K key, int hash,
82  *       InternalEntry<K, V> next) {
83  *     return new InternalEntry<K, V>(key, hash, null, next);
84  *   }
85  *   public InternalEntry<K, V> copyEntry(K key,
86  *       InternalEntry<K, V> original, InternalEntry<K, V> next) {
87  *     return new InternalEntry<K, V>(key, original.hash, original.value, next);
88  *   }
89  *   public void setValue(InternalEntry<K, V> entry, V value) {
90  *     entry.value = value;
91  *   }
92  *   public V getValue(InternalEntry<K, V> entry) { return entry.value; }
93  *   public boolean equalKeys(K a, Object b) { return a.equals(b); }
94  *   public boolean equalValues(V a, Object b) { return a.equals(b); }
95  *   public int hashKey(Object key) { return key.hashCode(); }
96  *   public K getKey(InternalEntry<K, V> entry) { return entry.key; }
97  *   public InternalEntry<K, V> getNext(InternalEntry<K, V> entry) {
98  *     return entry.next;
99  *   }
100  *   public int getHash(InternalEntry<K, V> entry) { return entry.hash; }
101  *   public void setInternals(CustomConcurrentHashMap.Internals<K, V,
102  *       InternalEntry<K, V>> internals) {} // ignored
103  * }
104  *
105  * class InternalEntry<K, V> {
106  *   final K key;
107  *   final int hash;
108  *   volatile V value;
109  *   final InternalEntry<K, V> next;
110  *   InternalEntry(K key, int hash, V value, InternalEntry<K, V> next) {
111  *     this.key = key;
112  *     this.hash = hash;
113  *     this.value = value;
114  *     this.next = next;
115  *   }
116  * }
117  * }</pre>
118  *
119  * To create a {@link java.util.concurrent.ConcurrentMap} using the strategy
120  * above:
121  *
122  * <pre>{@code
123  *   ConcurrentMap<K, V> map = new CustomConcurrentHashMap.Builder()
124  *       .build(new ConcurrentHashMapStrategy<K, V>());
125  * }</pre>
126  *
127  * @author Bob Lee
128  * @author Doug Lea
129  */
130 final class CustomConcurrentHashMap {
131 
132   /** Prevents instantiation. */
CustomConcurrentHashMap()133   private CustomConcurrentHashMap() {}
134 
135   /**
136    * Builds a custom concurrent hash map.
137    */
138   static final class Builder {
139     private static final int DEFAULT_INITIAL_CAPACITY = 16;
140     private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
141 
142     private static final int UNSET_INITIAL_CAPACITY = -1;
143     private static final int UNSET_CONCURRENCY_LEVEL = -1;
144 
145     int initialCapacity = UNSET_INITIAL_CAPACITY;
146     int concurrencyLevel = UNSET_CONCURRENCY_LEVEL;
147 
148     /**
149      * Sets a custom initial capacity (defaults to 16). Resizing this or any
150      * other kind of hash table is a relatively slow operation, so, when
151      * possible, it is a good idea to provide estimates of expected table
152      * sizes.
153      *
154      * @throws IllegalArgumentException if initialCapacity < 0
155      */
initialCapacity(int initialCapacity)156     public Builder initialCapacity(int initialCapacity) {
157       if (this.initialCapacity != UNSET_INITIAL_CAPACITY) {
158         throw new IllegalStateException(
159             "initial capacity was already set to " + this.initialCapacity);
160       }
161       if (initialCapacity < 0) {
162         throw new IllegalArgumentException();
163       }
164       this.initialCapacity = initialCapacity;
165       return this;
166     }
167 
168     /**
169      * Guides the allowed concurrency among update operations. Used as a
170      * hint for internal sizing. The table is internally partitioned to try to
171      * permit the indicated number of concurrent updates without contention.
172      * Because placement in hash tables is essentially random, the actual
173      * concurrency will vary. Ideally, you should choose a value to accommodate
174      * as many threads as will ever concurrently modify the table. Using a
175      * significantly higher value than you need can waste space and time,
176      * and a significantly lower value can lead to thread contention. But
177      * overestimates and underestimates within an order of magnitude do
178      * not usually have much noticeable impact. A value of one is
179      * appropriate when it is known that only one thread will modify and
180      * all others will only read. Defaults to {@literal 16}.
181      *
182      * @throws IllegalArgumentException if concurrencyLevel < 0
183      */
concurrencyLevel(int concurrencyLevel)184     public Builder concurrencyLevel(int concurrencyLevel) {
185       if (this.concurrencyLevel != UNSET_CONCURRENCY_LEVEL) {
186         throw new IllegalStateException(
187             "concurrency level was already set to " + this.concurrencyLevel);
188       }
189       if (concurrencyLevel <= 0) {
190         throw new IllegalArgumentException();
191       }
192       this.concurrencyLevel = concurrencyLevel;
193       return this;
194     }
195 
196     /**
197      * Creates a new concurrent hash map backed by the given strategy.
198      *
199      * @param strategy used to implement and manipulate the entries
200      *
201      * @param <K> the type of keys to be stored in the returned map
202      * @param <V> the type of values to be stored in the returned map
203      * @param <E> the type of internal entry to be stored in the returned map
204      *
205      * @throws NullPointerException if strategy is null
206      */
buildMap(Strategy<K, V, E> strategy)207     public <K, V, E> ConcurrentMap<K, V> buildMap(Strategy<K, V, E> strategy) {
208       if (strategy == null) {
209         throw new NullPointerException("strategy");
210       }
211       return new Impl<K, V, E>(strategy, this);
212     }
213 
214     /**
215      * Creates a {@link ConcurrentMap}, backed by the given strategy, that
216      * supports atomic, on-demand computation of values. {@link Map#get}
217      * returns the value corresponding to the given key, atomically computes
218      * it using the computer function passed to this builder, or waits for
219      * another thread to compute the value if necessary. Only one value will
220      * be computed for each key at a given time.
221      *
222      * <p>If an entry's value has not finished computing yet, query methods
223      * besides {@link java.util.Map#get} return immediately as if an entry
224      * doesn't exist. In other words, an entry isn't externally visible until
225      * the value's computation completes.
226      *
227      * <p>{@link Map#get} in the returned map implementation throws:
228      * <ul>
229      * <li>{@link NullPointerException} if the key is null or the
230      *  computer returns null</li>
231      * <li>or {@link ComputationException} wrapping an exception thrown by the
232      *  computation</li>
233      * </ul>
234      *
235      * <p><b>Note:</b> Callers of {@code get()} <i>must</i> ensure that the key
236      *  argument is of type {@code K}. {@code Map.get()} takes {@code Object},
237      *  so the key type is not checked at compile time. Passing an object of
238      *  a type other than {@code K} can result in that object being unsafely
239      *  passed to the computer function as type {@code K} not to mention the
240      *  unsafe key being stored in the map.
241      *
242      * @param strategy used to implement and manipulate the entries
243      * @param computer used to compute values for keys
244      *
245      * @param <K> the type of keys to be stored in the returned map
246      * @param <V> the type of values to be stored in the returned map
247      * @param <E> the type of internal entry to be stored in the returned map
248      *
249      * @throws NullPointerException if strategy or computer is null
250      */
buildComputingMap( ComputingStrategy<K, V, E> strategy, Function<? super K, ? extends V> computer)251     public <K, V, E> ConcurrentMap<K, V> buildComputingMap(
252         ComputingStrategy<K, V, E> strategy,
253         Function<? super K, ? extends V> computer) {
254       if (strategy == null) {
255         throw new NullPointerException("strategy");
256       }
257       if (computer == null) {
258         throw new NullPointerException("computer");
259       }
260 
261       return new ComputingImpl<K, V, E>(strategy, this, computer);
262     }
263 
getInitialCapacity()264     int getInitialCapacity() {
265       return (initialCapacity == UNSET_INITIAL_CAPACITY)
266           ? DEFAULT_INITIAL_CAPACITY : initialCapacity;
267     }
268 
getConcurrencyLevel()269     int getConcurrencyLevel() {
270       return (concurrencyLevel == UNSET_CONCURRENCY_LEVEL)
271           ? DEFAULT_CONCURRENCY_LEVEL : concurrencyLevel;
272     }
273   }
274 
275   /**
276    * Implements behavior specific to the client's concurrent hash map
277    * implementation. Used by the framework to create new entries and perform
278    * operations on them.
279    *
280    * <p>Method parameters are never null unless otherwise specified.
281    *
282    * <h3>Partially Reclaimed Entries</h3>
283    *
284    * <p>This class does <i>not</i> allow {@code null} to be used as a key.
285    * Setting values to null is not permitted, but entries may have null keys
286    * or values for various reasons. For example, the key or value may have
287    * been garbage collected or reclaimed through other means.
288    * CustomConcurrentHashMap treats entries with null keys and values as
289    * "partially reclaimed" and ignores them for the most part. Entries may
290    * enter a partially reclaimed state but they must not leave it. Partially
291    * reclaimed entries will not be copied over during table expansions, for
292    * example. Strategy implementations should proactively remove partially
293    * reclaimed entries so that {@link Map#isEmpty} and {@link Map#size()}
294    * return up-to-date results.
295    *
296    * @param <K> the type of keys to be stored in the returned map
297    * @param <V> the type of values to be stored in the returned map
298    * @param <E> internal entry type, not directly exposed to clients in map
299    *  views
300    */
301   public interface Strategy<K, V, E> {
302 
303     /**
304      * Constructs a new entry for the given key with a pointer to the given
305      * next entry.
306      *
307      * <p>This method may return different entry implementations
308      * depending upon whether next is null or not. For example, if next is
309      * null (as will often be the case), this factory might use an entry
310      * class that doesn't waste memory on an unnecessary field.
311      *
312      * @param key for this entry
313      * @param hash of key returned by {@link #hashKey}
314      * @param next entry (used when implementing a hash bucket as a linked
315      *  list, for example), possibly null
316      * @return a new entry
317      */
newEntry(K key, int hash, E next)318     abstract E newEntry(K key, int hash, E next);
319 
320     /**
321      * Creates a copy of the given entry pointing to the given next entry.
322      * Copies the value and any other implementation-specific state from
323      * {@code original} to the returned entry. For example,
324      * CustomConcurrentHashMap might use this method when removing other
325      * entries or expanding the internal table.
326      *
327      * @param key for {@code original} as well as the returned entry.
328      *  Explicitly provided here to prevent reclamation of the key at an
329      *  inopportune time in implementations that don't otherwise keep
330      *  a strong reference to the key.
331      * @param original entry from which the value and other
332      *  implementation-specific state should be copied
333      * @param newNext the next entry the new entry should point to, possibly
334      *  null
335      */
copyEntry(K key, E original, E newNext)336     E copyEntry(K key, E original, E newNext);
337 
338     /**
339      * Sets the value of an entry using volatile semantics. Values are set
340      * synchronously on a per-entry basis.
341      *
342      * @param entry to set the value on
343      * @param value to set
344      */
setValue(E entry, V value)345     void setValue(E entry, V value);
346 
347     /**
348      * Gets the value of an entry using volatile semantics.
349      *
350      * @param entry to get the value from
351      */
getValue(E entry)352     V getValue(E entry);
353 
354     /**
355      * Returns true if the two given keys are equal, false otherwise. Neither
356      * key will be null.
357      *
358      * @param a key from inside the map
359      * @param b key passed from caller, not necesarily of type K
360      *
361      * @see Object#equals the same contractual obligations apply here
362      */
equalKeys(K a, Object b)363     boolean equalKeys(K a, Object b);
364 
365     /**
366      * Returns true if the two given values are equal, false otherwise. Neither
367      * value will be null.
368      *
369      * @param a value from inside the map
370      * @param b value passed from caller, not necesarily of type V
371      *
372      * @see Object#equals the same contractual obligations apply here
373      */
equalValues(V a, Object b)374     boolean equalValues(V a, Object b);
375 
376     /**
377      * Returns a hash code for the given key.
378      *
379      * @see Object#hashCode the same contractual obligations apply here
380      */
hashKey(Object key)381     int hashKey(Object key);
382 
383     /**
384      * Gets the key for the given entry. This may return null (for example,
385      * if the key was reclaimed by the garbage collector).
386      *
387      * @param entry to get key from
388      * @return key from the given entry
389      */
getKey(E entry)390     K getKey(E entry);
391 
392     /**
393      * Gets the next entry relative to the given entry, the exact same entry
394      * that was provided to {@link Strategy#newEntry} when the given entry was
395      * created.
396      *
397      * @return the next entry or null if null was passed to
398      *  {@link Strategy#newEntry}
399      */
getNext(E entry)400     E getNext(E entry);
401 
402     /**
403      * Returns the hash code that was passed to {@link Strategy#newEntry})
404      * when the given entry was created.
405      */
getHash(E entry)406     int getHash(E entry);
407 
408 // TODO:
409 //    /**
410 //     * Notifies the strategy that an entry has been removed from the map.
411 //     *
412 //     * @param entry that was recently removed
413 //     */
414 //    void remove(E entry);
415 
416     /**
417      * Provides an API for interacting directly with the map's internal
418      * entries to this strategy. Invoked once when the map is created.
419      * Strategies that don't need access to the map's internal entries
420      * can simply ignore the argument.
421      *
422      * @param internals of the map, enables direct interaction with the
423      *  internal entries
424      */
setInternals(Internals<K, V, E> internals)425     void setInternals(Internals<K, V, E> internals);
426   }
427 
428   /**
429    * Provides access to a map's internal entries.
430    */
431   public interface Internals<K, V, E> {
432 
433 // TODO:
434 //    /**
435 //     * Returns a set view of the internal entries.
436 //     */
437 //    Set<E> entrySet();
438 
439     /**
440      * Returns the internal entry corresponding to the given key from the map.
441      *
442      * @param key to retrieve entry for
443      *
444      * @throws NullPointerException if key is null
445      */
getEntry(K key)446     E getEntry(K key);
447 
448     /**
449      * Removes the given entry from the map if the value of the entry in the
450      * map matches the given value.
451      *
452      * @param entry to remove
453      * @param value entry must have for the removal to succeed
454      *
455      * @throws NullPointerException if entry is null
456      */
removeEntry(E entry, @Nullable V value)457     boolean removeEntry(E entry, @Nullable V value);
458 
459     /**
460      * Removes the given entry from the map.
461      *
462      * @param entry to remove
463      *
464      * @throws NullPointerException if entry is null
465      */
removeEntry(E entry)466     boolean removeEntry(E entry);
467   }
468 
469   /**
470    * Extends {@link Strategy} to add support for computing values on-demand.
471    * Implementations should typically intialize the entry's value to a
472    * placeholder value in {@link #newEntry(Object, int, Object)} so that
473    * {@link #waitForValue(Object)} can tell the difference between a
474    * pre-intialized value and an in-progress computation. {@link
475    * #copyEntry(Object, Object, Object)} must detect and handle the case where
476    * an entry is copied in the middle of a computation. Implementations can
477    * throw {@link UnsupportedOperationException} in {@link #setValue(Object,
478    * Object)} if they wish to prevent users from setting values directly.
479    *
480    * @see Builder#buildComputingMap(CustomConcurrentHashMap.ComputingStrategy,
481    *     Function)
482    */
483   public interface ComputingStrategy<K, V, E> extends Strategy<K, V, E> {
484 
485     /**
486      * Computes a value for the given key and stores it in the given entry.
487      * Called as a result of {@link Map#get}. If this method throws an
488      * exception, CustomConcurrentHashMap will remove the entry and retry
489      * the computation on subsequent requests.
490      *
491      * @param entry that was created
492      * @param computer passed to {@link Builder#buildMap}
493      *
494      * @throws ComputationException if the computation threw an exception
495      * @throws NullPointerException if the computer returned null
496      *
497      * @return the computed value
498      */
compute(K key, E entry, Function<? super K, ? extends V> computer)499     V compute(K key, E entry, Function<? super K, ? extends V> computer);
500 
501     /**
502      * Gets a value from an entry waiting for the value to be set by {@link
503      * #compute} if necessary. Returns null if a value isn't available at
504      * which point CustomConcurrentHashMap tries to compute a new value.
505      *
506      * @param entry to return value from
507      * @return stored value or null if the value isn't available
508      *
509      * @throws InterruptedException if the thread was interrupted while
510      *  waiting
511      */
waitForValue(E entry)512     V waitForValue(E entry) throws InterruptedException;
513   }
514 
515   /**
516    * Applies a supplemental hash function to a given hash code, which defends
517    * against poor quality hash functions. This is critical when the
518    * concurrent hash map uses power-of-two length hash tables, that otherwise
519    * encounter collisions for hash codes that do not differ in lower or upper
520    * bits.
521    *
522    * @param h hash code
523    */
rehash(int h)524   private static int rehash(int h) {
525     // Spread bits to regularize both segment and index locations,
526     // using variant of single-word Wang/Jenkins hash.
527     h += (h << 15) ^ 0xffffcd7d;
528     h ^= (h >>> 10);
529     h += (h << 3);
530     h ^= (h >>> 6);
531     h += (h << 2) + (h << 14);
532     return h ^ (h >>> 16);
533   }
534 
535   /** The concurrent hash map implementation. */
536   static class Impl<K, V, E> extends AbstractMap<K, V>
537       implements ConcurrentMap<K, V>, Serializable {
538 
539     /*
540      * The basic strategy is to subdivide the table among Segments,
541      * each of which itself is a concurrently readable hash table.
542      */
543 
544     /* ---------------- Constants -------------- */
545 
546     /**
547      * The maximum capacity, used if a higher value is implicitly specified by
548      * either of the constructors with arguments.  MUST be a power of two <=
549      * 1<<30 to ensure that entries are indexable using ints.
550      */
551     static final int MAXIMUM_CAPACITY = 1 << 30;
552 
553     /**
554      * The maximum number of segments to allow; used to bound constructor
555      * arguments.
556      */
557     static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
558 
559     /**
560      * Number of unsynchronized retries in size and containsValue methods before
561      * resorting to locking. This is used to avoid unbounded retries if tables
562      * undergo continuous modification which would make it impossible to obtain
563      * an accurate result.
564      */
565     static final int RETRIES_BEFORE_LOCK = 2;
566 
567     /* ---------------- Fields -------------- */
568 
569     /**
570      * The strategy used to implement this map.
571      */
572     final Strategy<K, V, E> strategy;
573 
574     /**
575      * Mask value for indexing into segments. The upper bits of a key's hash
576      * code are used to choose the segment.
577      */
578     final int segmentMask;
579 
580     /**
581      * Shift value for indexing within segments. Helps prevent entries that
582      * end up in the same segment from also ending up in the same bucket.
583      */
584     final int segmentShift;
585 
586     /**
587      * The segments, each of which is a specialized hash table
588      */
589     final Segment[] segments;
590 
591     /**
592      * Creates a new, empty map with the specified strategy, initial capacity,
593      * load factor and concurrency level.
594      */
Impl(Strategy<K, V, E> strategy, Builder builder)595     Impl(Strategy<K, V, E> strategy, Builder builder) {
596       int concurrencyLevel = builder.getConcurrencyLevel();
597       int initialCapacity = builder.getInitialCapacity();
598 
599       if (concurrencyLevel > MAX_SEGMENTS) {
600         concurrencyLevel = MAX_SEGMENTS;
601       }
602 
603       // Find power-of-two sizes best matching arguments
604       int segmentShift = 0;
605       int segmentCount = 1;
606       while (segmentCount < concurrencyLevel) {
607         ++segmentShift;
608         segmentCount <<= 1;
609       }
610       this.segmentShift = 32 - segmentShift;
611       segmentMask = segmentCount - 1;
612       this.segments = newSegmentArray(segmentCount);
613 
614       if (initialCapacity > MAXIMUM_CAPACITY) {
615         initialCapacity = MAXIMUM_CAPACITY;
616       }
617 
618       int segmentCapacity = initialCapacity / segmentCount;
619       if (segmentCapacity * segmentCount < initialCapacity) {
620         ++segmentCapacity;
621       }
622 
623       int segmentSize = 1;
624       while (segmentSize < segmentCapacity) {
625           segmentSize <<= 1;
626       }
627       for (int i = 0; i < this.segments.length; ++i) {
628         this.segments[i] = new Segment(segmentSize);
629       }
630 
631       this.strategy = strategy;
632 
633       strategy.setInternals(new InternalsImpl());
634     }
635 
hash(Object key)636     int hash(Object key) {
637       int h = strategy.hashKey(key);
638       return rehash(h);
639     }
640 
641     class InternalsImpl implements Internals<K, V, E>, Serializable {
642 
643       static final long serialVersionUID = 0;
644 
getEntry(K key)645       public E getEntry(K key) {
646         if (key == null) {
647           throw new NullPointerException("key");
648         }
649         int hash = hash(key);
650         return segmentFor(hash).getEntry(key, hash);
651       }
652 
removeEntry(E entry, V value)653       public boolean removeEntry(E entry, V value) {
654         if (entry == null) {
655           throw new NullPointerException("entry");
656         }
657         int hash = strategy.getHash(entry);
658         return segmentFor(hash).removeEntry(entry, hash, value);
659       }
660 
removeEntry(E entry)661       public boolean removeEntry(E entry) {
662         if (entry == null) {
663           throw new NullPointerException("entry");
664         }
665         int hash = strategy.getHash(entry);
666         return segmentFor(hash).removeEntry(entry, hash);
667       }
668     }
669 
670     @SuppressWarnings("unchecked")
newSegmentArray(int ssize)671     Segment[] newSegmentArray(int ssize) {
672       // Note: This is the only way I could figure out how to create
673       // a segment array (the compile has a tough time with arrays of
674       // inner classes of generic types apparently). Safe because we're
675       // restricting what can go in the array and no one has an
676       // unrestricted reference.
677       return (Segment[]) Array.newInstance(Segment.class, ssize);
678     }
679 
680     /* ---------------- Small Utilities -------------- */
681 
682     /**
683      * Returns the segment that should be used for key with given hash
684      *
685      * @param hash the hash code for the key
686      * @return the segment
687      */
segmentFor(int hash)688     Segment segmentFor(int hash) {
689       return segments[(hash >>> segmentShift) & segmentMask];
690     }
691 
692     /* ---------------- Inner Classes -------------- */
693 
694     /**
695      * Segments are specialized versions of hash tables.  This subclasses from
696      * ReentrantLock opportunistically, just to simplify some locking and avoid
697      * separate construction.
698      */
699     @SuppressWarnings("serial") // This class is never serialized.
700     final class Segment extends ReentrantLock {
701 
702       /*
703        * Segments maintain a table of entry lists that are ALWAYS
704        * kept in a consistent state, so can be read without locking.
705        * Next fields of nodes are immutable (final).  All list
706        * additions are performed at the front of each bin. This
707        * makes it easy to check changes, and also fast to traverse.
708        * When nodes would otherwise be changed, new nodes are
709        * created to replace them. This works well for hash tables
710        * since the bin lists tend to be short. (The average length
711        * is less than two for the default load factor threshold.)
712        *
713        * Read operations can thus proceed without locking, but rely
714        * on selected uses of volatiles to ensure that completed
715        * write operations performed by other threads are
716        * noticed. For most purposes, the "count" field, tracking the
717        * number of elements, serves as that volatile variable
718        * ensuring visibility.  This is convenient because this field
719        * needs to be read in many read operations anyway:
720        *
721        *   - All (unsynchronized) read operations must first read the
722        *     "count" field, and should not look at table entries if
723        *     it is 0.
724        *
725        *   - All (synchronized) write operations should write to
726        *     the "count" field after structurally changing any bin.
727        *     The operations must not take any action that could even
728        *     momentarily cause a concurrent read operation to see
729        *     inconsistent data. This is made easier by the nature of
730        *     the read operations in Map. For example, no operation
731        *     can reveal that the table has grown but the threshold
732        *     has not yet been updated, so there are no atomicity
733        *     requirements for this with respect to reads.
734        *
735        * As a guide, all critical volatile reads and writes to the
736        * count field are marked in code comments.
737        */
738 
739       /**
740        * The number of elements in this segment's region.
741        */
742       volatile int count;
743 
744       /**
745        * Number of updates that alter the size of the table. This is used
746        * during bulk-read methods to make sure they see a consistent snapshot:
747        * If modCounts change during a traversal of segments computing size or
748        * checking containsValue, then we might have an inconsistent view of
749        * state so (usually) must retry.
750        */
751       int modCount;
752 
753       /**
754        * The table is expanded when its size exceeds this threshold. (The
755        * value of this field is always {@code (int)(capacity * loadFactor)}.)
756        */
757       int threshold;
758 
759       /**
760        * The per-segment table.
761        */
762       volatile AtomicReferenceArray<E> table;
763 
Segment(int initialCapacity)764       Segment(int initialCapacity) {
765         setTable(newEntryArray(initialCapacity));
766       }
767 
newEntryArray(int size)768       AtomicReferenceArray<E> newEntryArray(int size) {
769         return new AtomicReferenceArray<E>(size);
770       }
771 
772       /**
773        * Sets table to new HashEntry array. Call only while holding lock or in
774        * constructor.
775        */
setTable(AtomicReferenceArray<E> newTable)776       void setTable(AtomicReferenceArray<E> newTable) {
777         this.threshold = newTable.length() * 3 / 4;
778         this.table = newTable;
779       }
780 
781       /**
782        * Returns properly casted first entry of bin for given hash.
783        */
getFirst(int hash)784       E getFirst(int hash) {
785         AtomicReferenceArray<E> table = this.table;
786         return table.get(hash & (table.length() - 1));
787       }
788 
789       /* Specialized implementations of map methods */
790 
getEntry(Object key, int hash)791       public E getEntry(Object key, int hash) {
792         Strategy<K, V, E> s = Impl.this.strategy;
793         if (count != 0) { // read-volatile
794           for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
795             if (s.getHash(e) != hash) {
796               continue;
797             }
798 
799             K entryKey = s.getKey(e);
800             if (entryKey == null) {
801               continue;
802             }
803 
804             if (s.equalKeys(entryKey, key)) {
805               return e;
806             }
807           }
808         }
809 
810         return null;
811       }
812 
get(Object key, int hash)813       V get(Object key, int hash) {
814         E entry = getEntry(key, hash);
815         if (entry == null) {
816           return null;
817         }
818 
819         return strategy.getValue(entry);
820       }
821 
containsKey(Object key, int hash)822       boolean containsKey(Object key, int hash) {
823         Strategy<K, V, E> s = Impl.this.strategy;
824         if (count != 0) { // read-volatile
825           for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
826             if (s.getHash(e) != hash) {
827               continue;
828             }
829 
830             K entryKey = s.getKey(e);
831             if (entryKey == null) {
832               continue;
833             }
834 
835             if (s.equalKeys(entryKey, key)) {
836               // Return true only if this entry has a value.
837               return s.getValue(e) != null;
838             }
839           }
840         }
841 
842         return false;
843       }
844 
containsValue(Object value)845       boolean containsValue(Object value) {
846         Strategy<K, V, E> s = Impl.this.strategy;
847         if (count != 0) { // read-volatile
848           AtomicReferenceArray<E> table = this.table;
849           int length = table.length();
850           for (int i = 0; i < length; i++) {
851             for (E e = table.get(i); e != null; e = s.getNext(e)) {
852               V entryValue = s.getValue(e);
853 
854               // If the value disappeared, this entry is partially collected,
855               // and we should skip it.
856               if (entryValue == null) {
857                 continue;
858               }
859 
860               if (s.equalValues(entryValue, value)) {
861                 return true;
862               }
863             }
864           }
865         }
866 
867         return false;
868       }
869 
replace(K key, int hash, V oldValue, V newValue)870       boolean replace(K key, int hash, V oldValue, V newValue) {
871         Strategy<K, V, E> s = Impl.this.strategy;
872         lock();
873         try {
874           for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
875             K entryKey = s.getKey(e);
876             if (s.getHash(e) == hash && entryKey != null
877                 && s.equalKeys(key, entryKey)) {
878               // If the value disappeared, this entry is partially collected,
879               // and we should pretend like it doesn't exist.
880               V entryValue = s.getValue(e);
881               if (entryValue == null) {
882                 return false;
883               }
884 
885               if (s.equalValues(entryValue, oldValue)) {
886                 s.setValue(e, newValue);
887                 return true;
888               }
889             }
890           }
891 
892           return false;
893         } finally {
894           unlock();
895         }
896       }
897 
replace(K key, int hash, V newValue)898       V replace(K key, int hash, V newValue) {
899         Strategy<K, V, E> s = Impl.this.strategy;
900         lock();
901         try {
902           for (E e = getFirst(hash); e != null; e = s.getNext(e)) {
903             K entryKey = s.getKey(e);
904             if (s.getHash(e) == hash && entryKey != null
905                 && s.equalKeys(key, entryKey)) {
906               // If the value disappeared, this entry is partially collected,
907               // and we should pretend like it doesn't exist.
908               V entryValue = s.getValue(e);
909               if (entryValue == null) {
910                 return null;
911               }
912 
913               s.setValue(e, newValue);
914               return entryValue;
915             }
916           }
917 
918           return null;
919         } finally {
920           unlock();
921         }
922       }
923 
put(K key, int hash, V value, boolean onlyIfAbsent)924       V put(K key, int hash, V value, boolean onlyIfAbsent) {
925         Strategy<K, V, E> s = Impl.this.strategy;
926         lock();
927         try {
928           int count = this.count;
929           if (count++ > this.threshold) { // ensure capacity
930             expand();
931           }
932 
933           AtomicReferenceArray<E> table = this.table;
934           int index = hash & (table.length() - 1);
935 
936           E first = table.get(index);
937 
938           // Look for an existing entry.
939           for (E e = first; e != null; e = s.getNext(e)) {
940             K entryKey = s.getKey(e);
941             if (s.getHash(e) == hash && entryKey != null
942                 && s.equalKeys(key, entryKey)) {
943               // We found an existing entry.
944 
945               // If the value disappeared, this entry is partially collected,
946               // and we should pretend like it doesn't exist.
947               V entryValue = s.getValue(e);
948               if (onlyIfAbsent && entryValue != null) {
949                 return entryValue;
950               }
951 
952               s.setValue(e, value);
953               return entryValue;
954             }
955           }
956 
957           // Create a new entry.
958           ++modCount;
959           E newEntry = s.newEntry(key, hash, first);
960           s.setValue(newEntry, value);
961           table.set(index, newEntry);
962           this.count = count; // write-volatile
963           return null;
964         } finally {
965           unlock();
966         }
967       }
968 
969       /**
970        * Expands the table if possible.
971        */
expand()972       void expand() {
973         AtomicReferenceArray<E> oldTable = table;
974         int oldCapacity = oldTable.length();
975         if (oldCapacity >= MAXIMUM_CAPACITY) {
976           return;
977         }
978 
979         /*
980          * Reclassify nodes in each list to new Map.  Because we are
981          * using power-of-two expansion, the elements from each bin
982          * must either stay at same index, or move with a power of two
983          * offset. We eliminate unnecessary node creation by catching
984          * cases where old nodes can be reused because their next
985          * fields won't change. Statistically, at the default
986          * threshold, only about one-sixth of them need cloning when
987          * a table doubles. The nodes they replace will be garbage
988          * collectable as soon as they are no longer referenced by any
989          * reader thread that may be in the midst of traversing table
990          * right now.
991          */
992 
993         Strategy<K, V, E> s = Impl.this.strategy;
994         AtomicReferenceArray<E> newTable = newEntryArray(oldCapacity << 1);
995         threshold = newTable.length() * 3 / 4;
996         int newMask = newTable.length() - 1;
997         for (int oldIndex = 0; oldIndex < oldCapacity; oldIndex++) {
998           // We need to guarantee that any existing reads of old Map can
999           //  proceed. So we cannot yet null out each bin.
1000           E head = oldTable.get(oldIndex);
1001 
1002           if (head != null) {
1003             E next = s.getNext(head);
1004             int headIndex = s.getHash(head) & newMask;
1005 
1006             // Single node on list
1007             if (next == null) {
1008               newTable.set(headIndex, head);
1009             } else {
1010               // Reuse the consecutive sequence of nodes with the same target
1011               // index from the end of the list. tail points to the first
1012               // entry in the reusable list.
1013               E tail = head;
1014               int tailIndex = headIndex;
1015               for (E last = next; last != null; last = s.getNext(last)) {
1016                 int newIndex = s.getHash(last) & newMask;
1017                 if (newIndex != tailIndex) {
1018                   // The index changed. We'll need to copy the previous entry.
1019                   tailIndex = newIndex;
1020                   tail = last;
1021                 }
1022               }
1023               newTable.set(tailIndex, tail);
1024 
1025               // Clone nodes leading up to the tail.
1026               for (E e = head; e != tail; e = s.getNext(e)) {
1027                 K key = s.getKey(e);
1028                 if (key != null) {
1029                   int newIndex = s.getHash(e) & newMask;
1030                   E newNext = newTable.get(newIndex);
1031                   newTable.set(newIndex, s.copyEntry(key, e, newNext));
1032                 } else {
1033                   // Key was reclaimed. Skip entry.
1034                 }
1035               }
1036             }
1037           }
1038         }
1039         table = newTable;
1040       }
1041 
remove(Object key, int hash)1042       V remove(Object key, int hash) {
1043         Strategy<K, V, E> s = Impl.this.strategy;
1044         lock();
1045         try {
1046           int count = this.count - 1;
1047           AtomicReferenceArray<E> table = this.table;
1048           int index = hash & (table.length() - 1);
1049           E first = table.get(index);
1050 
1051           for (E e = first; e != null; e = s.getNext(e)) {
1052             K entryKey = s.getKey(e);
1053             if (s.getHash(e) == hash && entryKey != null
1054                 && s.equalKeys(entryKey, key)) {
1055               V entryValue = strategy.getValue(e);
1056               // All entries following removed node can stay
1057               // in list, but all preceding ones need to be
1058               // cloned.
1059               ++modCount;
1060               E newFirst = s.getNext(e);
1061               for (E p = first; p != e; p = s.getNext(p)) {
1062                 K pKey = s.getKey(p);
1063                 if (pKey != null) {
1064                   newFirst = s.copyEntry(pKey, p, newFirst);
1065                 } else {
1066                   // Key was reclaimed. Skip entry.
1067                 }
1068               }
1069               table.set(index, newFirst);
1070               this.count = count; // write-volatile
1071               return entryValue;
1072             }
1073           }
1074 
1075           return null;
1076         } finally {
1077           unlock();
1078         }
1079       }
1080 
remove(Object key, int hash, Object value)1081       boolean remove(Object key, int hash, Object value) {
1082         Strategy<K, V, E> s = Impl.this.strategy;
1083         lock();
1084         try {
1085           int count = this.count - 1;
1086           AtomicReferenceArray<E> table = this.table;
1087           int index = hash & (table.length() - 1);
1088           E first = table.get(index);
1089 
1090           for (E e = first; e != null; e = s.getNext(e)) {
1091             K entryKey = s.getKey(e);
1092             if (s.getHash(e) == hash && entryKey != null
1093                 && s.equalKeys(entryKey, key)) {
1094               V entryValue = strategy.getValue(e);
1095               if (value == entryValue || (value != null && entryValue != null
1096                   && s.equalValues(entryValue, value))) {
1097                 // All entries following removed node can stay
1098                 // in list, but all preceding ones need to be
1099                 // cloned.
1100                 ++modCount;
1101                 E newFirst = s.getNext(e);
1102                 for (E p = first; p != e; p = s.getNext(p)) {
1103                   K pKey = s.getKey(p);
1104                   if (pKey != null) {
1105                     newFirst = s.copyEntry(pKey, p, newFirst);
1106                   } else {
1107                     // Key was reclaimed. Skip entry.
1108                   }
1109                 }
1110                 table.set(index, newFirst);
1111                 this.count = count; // write-volatile
1112                 return true;
1113               } else {
1114                 return false;
1115               }
1116             }
1117           }
1118 
1119           return false;
1120         } finally {
1121           unlock();
1122         }
1123       }
1124 
removeEntry(E entry, int hash, V value)1125       public boolean removeEntry(E entry, int hash, V value) {
1126         Strategy<K, V, E> s = Impl.this.strategy;
1127         lock();
1128         try {
1129           int count = this.count - 1;
1130           AtomicReferenceArray<E> table = this.table;
1131           int index = hash & (table.length() - 1);
1132           E first = table.get(index);
1133 
1134           for (E e = first; e != null; e = s.getNext(e)) {
1135             if (s.getHash(e) == hash && entry.equals(e)) {
1136               V entryValue = s.getValue(e);
1137               if (entryValue == value || (value != null
1138                   && s.equalValues(entryValue, value))) {
1139                 // All entries following removed node can stay
1140                 // in list, but all preceding ones need to be
1141                 // cloned.
1142                 ++modCount;
1143                 E newFirst = s.getNext(e);
1144                 for (E p = first; p != e; p = s.getNext(p)) {
1145                   K pKey = s.getKey(p);
1146                   if (pKey != null) {
1147                     newFirst = s.copyEntry(pKey, p, newFirst);
1148                   } else {
1149                     // Key was reclaimed. Skip entry.
1150                   }
1151                 }
1152                 table.set(index, newFirst);
1153                 this.count = count; // write-volatile
1154                 return true;
1155               } else {
1156                 return false;
1157               }
1158             }
1159           }
1160 
1161           return false;
1162         } finally {
1163           unlock();
1164         }
1165       }
1166 
removeEntry(E entry, int hash)1167       public boolean removeEntry(E entry, int hash) {
1168         Strategy<K, V, E> s = Impl.this.strategy;
1169         lock();
1170         try {
1171           int count = this.count - 1;
1172           AtomicReferenceArray<E> table = this.table;
1173           int index = hash & (table.length() - 1);
1174           E first = table.get(index);
1175 
1176           for (E e = first; e != null; e = s.getNext(e)) {
1177             if (s.getHash(e) == hash && entry.equals(e)) {
1178               // All entries following removed node can stay
1179               // in list, but all preceding ones need to be
1180               // cloned.
1181               ++modCount;
1182               E newFirst = s.getNext(e);
1183               for (E p = first; p != e; p = s.getNext(p)) {
1184                 K pKey = s.getKey(p);
1185                 if (pKey != null) {
1186                   newFirst = s.copyEntry(pKey, p, newFirst);
1187                 } else {
1188                   // Key was reclaimed. Skip entry.
1189                 }
1190               }
1191               table.set(index, newFirst);
1192               this.count = count; // write-volatile
1193               return true;
1194             }
1195           }
1196 
1197           return false;
1198         } finally {
1199           unlock();
1200         }
1201       }
1202 
clear()1203       void clear() {
1204         if (count != 0) {
1205           lock();
1206           try {
1207             AtomicReferenceArray<E> table = this.table;
1208             for (int i = 0; i < table.length(); i++) {
1209               table.set(i, null);
1210             }
1211             ++modCount;
1212             count = 0; // write-volatile
1213           } finally {
1214             unlock();
1215           }
1216         }
1217       }
1218     }
1219 
1220     /* ---------------- Public operations -------------- */
1221 
1222     /**
1223      * Returns {@code true} if this map contains no key-value mappings.
1224      *
1225      * @return {@code true} if this map contains no key-value mappings
1226      */
isEmpty()1227     @Override public boolean isEmpty() {
1228       final Segment[] segments = this.segments;
1229       /*
1230        * We keep track of per-segment modCounts to avoid ABA
1231        * problems in which an element in one segment was added and
1232        * in another removed during traversal, in which case the
1233        * table was never actually empty at any point. Note the
1234        * similar use of modCounts in the size() and containsValue()
1235        * methods, which are the only other methods also susceptible
1236        * to ABA problems.
1237        */
1238       int[] mc = new int[segments.length];
1239       int mcsum = 0;
1240       for (int i = 0; i < segments.length; ++i) {
1241         if (segments[i].count != 0) {
1242           return false;
1243         } else {
1244           mcsum += mc[i] = segments[i].modCount;
1245         }
1246       }
1247       // If mcsum happens to be zero, then we know we got a snapshot
1248       // before any modifications at all were made.  This is
1249       // probably common enough to bother tracking.
1250       if (mcsum != 0) {
1251         for (int i = 0; i < segments.length; ++i) {
1252           if (segments[i].count != 0 ||
1253               mc[i] != segments[i].modCount) {
1254             return false;
1255           }
1256         }
1257       }
1258       return true;
1259     }
1260 
1261     /**
1262      * Returns the number of key-value mappings in this map.  If the map
1263      * contains more than {@code Integer.MAX_VALUE} elements, returns
1264      * {@code Integer.MAX_VALUE}.
1265      *
1266      * @return the number of key-value mappings in this map
1267      */
size()1268     @Override public int size() {
1269       final Segment[] segments = this.segments;
1270       long sum = 0;
1271       long check = 0;
1272       int[] mc = new int[segments.length];
1273       // Try a few times to get accurate count. On failure due to
1274       // continuous async changes in table, resort to locking.
1275       for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
1276         check = 0;
1277         sum = 0;
1278         int mcsum = 0;
1279         for (int i = 0; i < segments.length; ++i) {
1280           sum += segments[i].count;
1281           mcsum += mc[i] = segments[i].modCount;
1282         }
1283         if (mcsum != 0) {
1284           for (int i = 0; i < segments.length; ++i) {
1285             check += segments[i].count;
1286             if (mc[i] != segments[i].modCount) {
1287               check = -1; // force retry
1288               break;
1289             }
1290           }
1291         }
1292         if (check == sum) {
1293           break;
1294         }
1295       }
1296       if (check != sum) { // Resort to locking all segments
1297         sum = 0;
1298         for (Segment segment : segments) {
1299           segment.lock();
1300         }
1301         for (Segment segment : segments) {
1302           sum += segment.count;
1303         }
1304         for (Segment segment : segments) {
1305           segment.unlock();
1306         }
1307       }
1308       if (sum > Integer.MAX_VALUE) {
1309         return Integer.MAX_VALUE;
1310       } else {
1311         return (int) sum;
1312       }
1313     }
1314 
1315     /**
1316      * Returns the value to which the specified key is mapped, or {@code null}
1317      * if this map contains no mapping for the key.
1318      *
1319      * <p>More formally, if this map contains a mapping from a key {@code k} to
1320      * a value {@code v} such that {@code key.equals(k)}, then this method
1321      * returns {@code v}; otherwise it returns {@code null}.  (There can be at
1322      * most one such mapping.)
1323      *
1324      * @throws NullPointerException if the specified key is null
1325      */
get(Object key)1326     @Override public V get(Object key) {
1327       if (key == null) {
1328         throw new NullPointerException("key");
1329       }
1330       int hash = hash(key);
1331       return segmentFor(hash).get(key, hash);
1332     }
1333 
1334     /**
1335      * Tests if the specified object is a key in this table.
1336      *
1337      * @param key possible key
1338      * @return {@code true} if and only if the specified object is a key in
1339      *         this table, as determined by the {@code equals} method;
1340      *         {@code false} otherwise.
1341      * @throws NullPointerException if the specified key is null
1342      */
containsKey(Object key)1343     @Override public boolean containsKey(Object key) {
1344       if (key == null) {
1345         throw new NullPointerException("key");
1346       }
1347       int hash = hash(key);
1348       return segmentFor(hash).containsKey(key, hash);
1349     }
1350 
1351     /**
1352      * Returns {@code true} if this map maps one or more keys to the specified
1353      * value. Note: This method requires a full internal traversal of the hash
1354      * table, and so is much slower than method {@code containsKey}.
1355      *
1356      * @param value value whose presence in this map is to be tested
1357      * @return {@code true} if this map maps one or more keys to the specified
1358      *         value
1359      * @throws NullPointerException if the specified value is null
1360      */
containsValue(Object value)1361     @Override public boolean containsValue(Object value) {
1362       if (value == null) {
1363         throw new NullPointerException("value");
1364       }
1365 
1366       // See explanation of modCount use above
1367 
1368       final Segment[] segments = this.segments;
1369       int[] mc = new int[segments.length];
1370 
1371       // Try a few times without locking
1372       for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
1373         int mcsum = 0;
1374         for (int i = 0; i < segments.length; ++i) {
1375           @SuppressWarnings("UnusedDeclaration")
1376           int c = segments[i].count;
1377           mcsum += mc[i] = segments[i].modCount;
1378           if (segments[i].containsValue(value)) {
1379             return true;
1380           }
1381         }
1382         boolean cleanSweep = true;
1383         if (mcsum != 0) {
1384           for (int i = 0; i < segments.length; ++i) {
1385             @SuppressWarnings("UnusedDeclaration")
1386             int c = segments[i].count;
1387             if (mc[i] != segments[i].modCount) {
1388               cleanSweep = false;
1389               break;
1390             }
1391           }
1392         }
1393         if (cleanSweep) {
1394           return false;
1395         }
1396       }
1397       // Resort to locking all segments
1398       for (Segment segment : segments) {
1399         segment.lock();
1400       }
1401       boolean found = false;
1402       try {
1403         for (Segment segment : segments) {
1404           if (segment.containsValue(value)) {
1405             found = true;
1406             break;
1407           }
1408         }
1409       } finally {
1410         for (Segment segment : segments) {
1411           segment.unlock();
1412         }
1413       }
1414       return found;
1415     }
1416 
1417     /**
1418      * Maps the specified key to the specified value in this table. Neither the
1419      * key nor the value can be null.
1420      *
1421      * <p> The value can be retrieved by calling the {@code get} method with a
1422      * key that is equal to the original key.
1423      *
1424      * @param key   key with which the specified value is to be associated
1425      * @param value value to be associated with the specified key
1426      * @return the previous value associated with {@code key}, or {@code null}
1427      *         if there was no mapping for {@code key}
1428      * @throws NullPointerException if the specified key or value is null
1429      */
put(K key, V value)1430     @Override public V put(K key, V value) {
1431       if (key == null) {
1432         throw new NullPointerException("key");
1433       }
1434       if (value == null) {
1435         throw new NullPointerException("value");
1436       }
1437       int hash = hash(key);
1438       return segmentFor(hash).put(key, hash, value, false);
1439     }
1440 
1441     /**
1442      * {@inheritDoc}
1443      *
1444      * @return the previous value associated with the specified key, or
1445      *         {@code null} if there was no mapping for the key
1446      * @throws NullPointerException if the specified key or value is null
1447      */
putIfAbsent(K key, V value)1448     public V putIfAbsent(K key, V value) {
1449       if (key == null) {
1450         throw new NullPointerException("key");
1451       }
1452       if (value == null) {
1453         throw new NullPointerException("value");
1454       }
1455       int hash = hash(key);
1456       return segmentFor(hash).put(key, hash, value, true);
1457     }
1458 
1459     /**
1460      * Copies all of the mappings from the specified map to this one. These
1461      * mappings replace any mappings that this map had for any of the keys
1462      * currently in the specified map.
1463      *
1464      * @param m mappings to be stored in this map
1465      */
putAll(Map<? extends K, ? extends V> m)1466     @Override public void putAll(Map<? extends K, ? extends V> m) {
1467       for (Entry<? extends K, ? extends V> e : m.entrySet()) {
1468         put(e.getKey(), e.getValue());
1469       }
1470     }
1471 
1472     /**
1473      * Removes the key (and its corresponding value) from this map. This method
1474      * does nothing if the key is not in the map.
1475      *
1476      * @param key the key that needs to be removed
1477      * @return the previous value associated with {@code key}, or {@code null}
1478      *         if there was no mapping for {@code key}
1479      * @throws NullPointerException if the specified key is null
1480      */
remove(Object key)1481     @Override public V remove(Object key) {
1482       if (key == null) {
1483         throw new NullPointerException("key");
1484       }
1485       int hash = hash(key);
1486       return segmentFor(hash).remove(key, hash);
1487     }
1488 
1489     /**
1490      * {@inheritDoc}
1491      *
1492      * @throws NullPointerException if the specified key is null
1493      */
remove(Object key, Object value)1494     public boolean remove(Object key, Object value) {
1495       if (key == null) {
1496         throw new NullPointerException("key");
1497       }
1498       int hash = hash(key);
1499       return segmentFor(hash).remove(key, hash, value);
1500     }
1501 
1502     /**
1503      * {@inheritDoc}
1504      *
1505      * @throws NullPointerException if any of the arguments are null
1506      */
replace(K key, V oldValue, V newValue)1507     public boolean replace(K key, V oldValue, V newValue) {
1508       if (key == null) {
1509         throw new NullPointerException("key");
1510       }
1511       if (oldValue == null) {
1512         throw new NullPointerException("oldValue");
1513       }
1514       if (newValue == null) {
1515         throw new NullPointerException("newValue");
1516       }
1517       int hash = hash(key);
1518       return segmentFor(hash).replace(key, hash, oldValue, newValue);
1519     }
1520 
1521     /**
1522      * {@inheritDoc}
1523      *
1524      * @return the previous value associated with the specified key, or
1525      *         {@code null} if there was no mapping for the key
1526      * @throws NullPointerException if the specified key or value is null
1527      */
replace(K key, V value)1528     public V replace(K key, V value) {
1529       if (key == null) {
1530         throw new NullPointerException("key");
1531       }
1532       if (value == null) {
1533         throw new NullPointerException("value");
1534       }
1535       int hash = hash(key);
1536       return segmentFor(hash).replace(key, hash, value);
1537     }
1538 
1539     /**
1540      * Removes all of the mappings from this map.
1541      */
clear()1542     @Override public void clear() {
1543       for (Segment segment : segments) {
1544         segment.clear();
1545       }
1546     }
1547 
1548     Set<K> keySet;
1549 
1550     /**
1551      * Returns a {@link java.util.Set} view of the keys contained in this map.
1552      * The set is backed by the map, so changes to the map are reflected in the
1553      * set, and vice-versa. The set supports element removal, which removes the
1554      * corresponding mapping from this map, via the {@code Iterator.remove},
1555      * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and
1556      * {@code clear} operations. It does not support the {@code add} or
1557      * {@code addAll} operations.
1558      *
1559      * <p>The view's {@code iterator} is a "weakly consistent" iterator that
1560      * will never throw {@link java.util.ConcurrentModificationException}, and
1561      * guarantees to traverse elements as they existed upon construction of the
1562      * iterator, and may (but is not guaranteed to) reflect any modifications
1563      * subsequent to construction.
1564      */
keySet()1565     @Override public Set<K> keySet() {
1566       Set<K> ks = keySet;
1567       return (ks != null) ? ks : (keySet = new KeySet());
1568     }
1569 
1570     Collection<V> values;
1571 
1572     /**
1573      * Returns a {@link java.util.Collection} view of the values contained in
1574      * this map. The collection is backed by the map, so changes to the map are
1575      * reflected in the collection, and vice-versa. The collection supports
1576      * element removal, which removes the corresponding mapping from this map,
1577      * via the {@code Iterator.remove}, {@code Collection.remove},
1578      * {@code removeAll}, {@code retainAll}, and {@code clear} operations. It
1579      * does not support the {@code add} or {@code addAll} operations.
1580      *
1581      * <p>The view's {@code iterator} is a "weakly consistent" iterator that
1582      * will never throw {@link java.util.ConcurrentModificationException}, and
1583      * guarantees to traverse elements as they existed upon construction of the
1584      * iterator, and may (but is not guaranteed to) reflect any modifications
1585      * subsequent to construction.
1586      */
values()1587     @Override public Collection<V> values() {
1588       Collection<V> vs = values;
1589       return (vs != null) ? vs : (values = new Values());
1590     }
1591 
1592     Set<Entry<K, V>> entrySet;
1593 
1594     /**
1595      * Returns a {@link java.util.Set} view of the mappings contained in this
1596      * map. The set is backed by the map, so changes to the map are reflected in
1597      * the set, and vice-versa. The set supports element removal, which removes
1598      * the corresponding mapping from the map, via the {@code Iterator.remove},
1599      * {@code Set.remove}, {@code removeAll}, {@code retainAll}, and
1600      * {@code clear} operations. It does not support the {@code add} or
1601      * {@code addAll} operations.
1602      *
1603      * <p>The view's {@code iterator} is a "weakly consistent" iterator that
1604      * will never throw {@link java.util.ConcurrentModificationException}, and
1605      * guarantees to traverse elements as they existed upon construction of the
1606      * iterator, and may (but is not guaranteed to) reflect any modifications
1607      * subsequent to construction.
1608      */
entrySet()1609     @Override public Set<Entry<K, V>> entrySet() {
1610       Set<Entry<K, V>> es = entrySet;
1611       return (es != null) ? es : (entrySet = new EntrySet());
1612     }
1613 
1614     /* ---------------- Iterator Support -------------- */
1615 
1616     abstract class HashIterator {
1617 
1618       int nextSegmentIndex;
1619       int nextTableIndex;
1620       AtomicReferenceArray<E> currentTable;
1621       E nextEntry;
1622       WriteThroughEntry nextExternal;
1623       WriteThroughEntry lastReturned;
1624 
HashIterator()1625       HashIterator() {
1626         nextSegmentIndex = segments.length - 1;
1627         nextTableIndex = -1;
1628         advance();
1629       }
1630 
hasMoreElements()1631       public boolean hasMoreElements() {
1632         return hasNext();
1633       }
1634 
advance()1635       final void advance() {
1636         nextExternal = null;
1637 
1638         if (nextInChain()) {
1639           return;
1640         }
1641 
1642         if (nextInTable()) {
1643           return;
1644         }
1645 
1646         while (nextSegmentIndex >= 0) {
1647           Segment seg = segments[nextSegmentIndex--];
1648           if (seg.count != 0) {
1649             currentTable = seg.table;
1650             nextTableIndex = currentTable.length() - 1;
1651             if (nextInTable()) {
1652               return;
1653             }
1654           }
1655         }
1656       }
1657 
1658       /**
1659        * Finds the next entry in the current chain. Returns true if an entry
1660        * was found.
1661        */
nextInChain()1662       boolean nextInChain() {
1663         Strategy<K, V, E> s = Impl.this.strategy;
1664         if (nextEntry != null) {
1665           for (nextEntry = s.getNext(nextEntry); nextEntry != null;
1666               nextEntry = s.getNext(nextEntry)) {
1667             if (advanceTo(nextEntry)) {
1668               return true;
1669             }
1670           }
1671         }
1672         return false;
1673       }
1674 
1675       /**
1676        * Finds the next entry in the current table. Returns true if an entry
1677        * was found.
1678        */
nextInTable()1679       boolean nextInTable() {
1680         while (nextTableIndex >= 0) {
1681           if ((nextEntry = currentTable.get(nextTableIndex--)) != null) {
1682             if (advanceTo(nextEntry) || nextInChain()) {
1683               return true;
1684             }
1685           }
1686         }
1687         return false;
1688       }
1689 
1690       /**
1691        * Advances to the given entry. Returns true if the entry was valid,
1692        * false if it should be skipped.
1693        */
advanceTo(E entry)1694       boolean advanceTo(E entry) {
1695         Strategy<K, V, E> s = Impl.this.strategy;
1696         K key = s.getKey(entry);
1697         V value = s.getValue(entry);
1698         if (key != null && value != null) {
1699           nextExternal = new WriteThroughEntry(key, value);
1700           return true;
1701         } else {
1702           // Skip partially reclaimed entry.
1703           return false;
1704         }
1705       }
1706 
hasNext()1707       public boolean hasNext() {
1708         return nextExternal != null;
1709       }
1710 
nextEntry()1711       WriteThroughEntry nextEntry() {
1712         if (nextExternal == null) {
1713           throw new NoSuchElementException();
1714         }
1715         lastReturned = nextExternal;
1716         advance();
1717         return lastReturned;
1718       }
1719 
remove()1720       public void remove() {
1721         if (lastReturned == null) {
1722           throw new IllegalStateException();
1723         }
1724         Impl.this.remove(lastReturned.getKey());
1725         lastReturned = null;
1726       }
1727     }
1728 
1729     final class KeyIterator extends HashIterator implements Iterator<K> {
1730 
next()1731       public K next() {
1732         return super.nextEntry().getKey();
1733       }
1734     }
1735 
1736     final class ValueIterator extends HashIterator implements Iterator<V> {
1737 
next()1738       public V next() {
1739         return super.nextEntry().getValue();
1740       }
1741     }
1742 
1743     /**
1744      * Custom Entry class used by EntryIterator.next(), that relays setValue
1745      * changes to the underlying map.
1746      */
1747     final class WriteThroughEntry extends AbstractMapEntry<K, V> {
1748       final K key;
1749       V value;
1750 
WriteThroughEntry(K key, V value)1751       WriteThroughEntry(K key, V value) {
1752         this.key = key;
1753         this.value = value;
1754       }
1755 
getKey()1756       @Override public K getKey() {
1757         return key;
1758       }
1759 
getValue()1760       @Override public V getValue() {
1761         return value;
1762       }
1763 
1764       /**
1765        * Set our entry's value and write through to the map. The value to
1766        * return is somewhat arbitrary here. Since a WriteThroughEntry does not
1767        * necessarily track asynchronous changes, the most recent "previous"
1768        * value could be different from what we return (or could even have been
1769        * removed in which case the put will re-establish). We do not and
1770        * cannot guarantee more.
1771        */
setValue(V value)1772       @Override public V setValue(V value) {
1773         if (value == null) {
1774           throw new NullPointerException();
1775         }
1776         V oldValue = Impl.this.put(getKey(), value);
1777         this.value = value;
1778         return oldValue;
1779       }
1780     }
1781 
1782     final class EntryIterator extends HashIterator
1783         implements Iterator<Entry<K, V>> {
1784 
next()1785       public Entry<K, V> next() {
1786         return nextEntry();
1787       }
1788     }
1789 
1790     final class KeySet extends AbstractSet<K> {
1791 
iterator()1792       @Override public Iterator<K> iterator() {
1793         return new KeyIterator();
1794       }
1795 
size()1796       @Override public int size() {
1797         return Impl.this.size();
1798       }
1799 
isEmpty()1800       @Override public boolean isEmpty() {
1801         return Impl.this.isEmpty();
1802       }
1803 
contains(Object o)1804       @Override public boolean contains(Object o) {
1805         return Impl.this.containsKey(o);
1806       }
1807 
remove(Object o)1808       @Override public boolean remove(Object o) {
1809         return Impl.this.remove(o) != null;
1810       }
1811 
clear()1812       @Override public void clear() {
1813         Impl.this.clear();
1814       }
1815     }
1816 
1817     final class Values extends AbstractCollection<V> {
1818 
iterator()1819       @Override public Iterator<V> iterator() {
1820         return new ValueIterator();
1821       }
1822 
size()1823       @Override public int size() {
1824         return Impl.this.size();
1825       }
1826 
isEmpty()1827       @Override public boolean isEmpty() {
1828         return Impl.this.isEmpty();
1829       }
1830 
contains(Object o)1831       @Override public boolean contains(Object o) {
1832         return Impl.this.containsValue(o);
1833       }
1834 
clear()1835       @Override public void clear() {
1836         Impl.this.clear();
1837       }
1838     }
1839 
1840     final class EntrySet extends AbstractSet<Entry<K, V>> {
1841 
iterator()1842       @Override public Iterator<Entry<K, V>> iterator() {
1843         return new EntryIterator();
1844       }
1845 
contains(Object o)1846       @Override public boolean contains(Object o) {
1847         if (!(o instanceof Entry)) {
1848           return false;
1849         }
1850         Entry<?, ?> e = (Entry<?, ?>) o;
1851         Object key = e.getKey();
1852         if (key == null) {
1853           return false;
1854         }
1855         V v = Impl.this.get(key);
1856 
1857         return v != null && strategy.equalValues(v, e.getValue());
1858       }
1859 
remove(Object o)1860       @Override public boolean remove(Object o) {
1861         if (!(o instanceof Entry)) {
1862           return false;
1863         }
1864         Entry<?, ?> e = (Entry<?, ?>) o;
1865         Object key = e.getKey();
1866         return key != null && Impl.this.remove(key, e.getValue());
1867       }
1868 
size()1869       @Override public int size() {
1870         return Impl.this.size();
1871       }
1872 
isEmpty()1873       @Override public boolean isEmpty() {
1874         return Impl.this.isEmpty();
1875       }
1876 
clear()1877       @Override public void clear() {
1878         Impl.this.clear();
1879       }
1880     }
1881 
1882     /* ---------------- Serialization Support -------------- */
1883 
1884     private static final long serialVersionUID = 1;
1885 
writeObject(java.io.ObjectOutputStream out)1886     private void writeObject(java.io.ObjectOutputStream out)
1887         throws IOException {
1888       out.writeInt(size());
1889       out.writeInt(segments.length); // concurrencyLevel
1890       out.writeObject(strategy);
1891       for (Entry<K, V> entry : entrySet()) {
1892         out.writeObject(entry.getKey());
1893         out.writeObject(entry.getValue());
1894       }
1895       out.writeObject(null); // terminate entries
1896     }
1897 
1898     /**
1899      * Fields used during deserialization. We use a nested class so we don't
1900      * load them until we need them. We need to use reflection to set final
1901      * fields outside of the constructor.
1902      */
1903     static class Fields {
1904 
1905       static final Field segmentShift = findField("segmentShift");
1906       static final Field segmentMask = findField("segmentMask");
1907       static final Field segments = findField("segments");
1908       static final Field strategy = findField("strategy");
1909 
findField(String name)1910       static Field findField(String name) {
1911         try {
1912           Field f = Impl.class.getDeclaredField(name);
1913           f.setAccessible(true);
1914           return f;
1915         } catch (NoSuchFieldException e) {
1916           throw new AssertionError(e);
1917         }
1918       }
1919     }
1920 
1921     @SuppressWarnings("unchecked")
readObject(java.io.ObjectInputStream in)1922     private void readObject(java.io.ObjectInputStream in)
1923         throws IOException, ClassNotFoundException {
1924       try {
1925         int initialCapacity = in.readInt();
1926         int concurrencyLevel = in.readInt();
1927         Strategy<K, V, E> strategy = (Strategy<K, V, E>) in.readObject();
1928 
1929         if (concurrencyLevel > MAX_SEGMENTS) {
1930           concurrencyLevel = MAX_SEGMENTS;
1931         }
1932 
1933         // Find power-of-two sizes best matching arguments
1934         int segmentShift = 0;
1935         int segmentCount = 1;
1936         while (segmentCount < concurrencyLevel) {
1937           ++segmentShift;
1938           segmentCount <<= 1;
1939         }
1940         Fields.segmentShift.set(this, 32 - segmentShift);
1941         Fields.segmentMask.set(this, segmentCount - 1);
1942         Fields.segments.set(this, newSegmentArray(segmentCount));
1943 
1944         if (initialCapacity > MAXIMUM_CAPACITY) {
1945           initialCapacity = MAXIMUM_CAPACITY;
1946         }
1947 
1948         int segmentCapacity = initialCapacity / segmentCount;
1949         if (segmentCapacity * segmentCount < initialCapacity) {
1950           ++segmentCapacity;
1951         }
1952 
1953         int segmentSize = 1;
1954         while (segmentSize < segmentCapacity) {
1955             segmentSize <<= 1;
1956         }
1957         for (int i = 0; i < this.segments.length; ++i) {
1958           this.segments[i] = new Segment(segmentSize);
1959         }
1960 
1961         Fields.strategy.set(this, strategy);
1962 
1963         while (true) {
1964           K key = (K) in.readObject();
1965           if (key == null) {
1966             break; // terminator
1967           }
1968           V value = (V) in.readObject();
1969           put(key, value);
1970         }
1971       } catch (IllegalAccessException e) {
1972         throw new AssertionError(e);
1973       }
1974     }
1975   }
1976 
1977   static class ComputingImpl<K, V, E> extends Impl<K, V, E> {
1978 
1979     static final long serialVersionUID = 0;
1980 
1981     final ComputingStrategy<K, V, E> computingStrategy;
1982     final Function<? super K, ? extends V> computer;
1983 
1984     /**
1985      * Creates a new, empty map with the specified strategy, initial capacity,
1986      * load factor and concurrency level.
1987      */
ComputingImpl(ComputingStrategy<K, V, E> strategy, Builder builder, Function<? super K, ? extends V> computer)1988     ComputingImpl(ComputingStrategy<K, V, E> strategy, Builder builder,
1989         Function<? super K, ? extends V> computer) {
1990       super(strategy, builder);
1991       this.computingStrategy = strategy;
1992       this.computer = computer;
1993     }
1994 
get(Object k)1995     @Override public V get(Object k) {
1996       /*
1997        * This cast isn't safe, but we can rely on the fact that K is almost
1998        * always passed to Map.get(), and tools like IDEs and Findbugs can
1999        * catch situations where this isn't the case.
2000        *
2001        * The alternative is to add an overloaded method, but the chances of
2002        * a user calling get() instead of the new API and the risks inherent
2003        * in adding a new API outweigh this little hole.
2004        */
2005       @SuppressWarnings("unchecked")
2006       K key = (K) k;
2007 
2008       if (key == null) {
2009         throw new NullPointerException("key");
2010       }
2011 
2012       int hash = hash(key);
2013       Segment segment = segmentFor(hash);
2014       outer: while (true) {
2015         E entry = segment.getEntry(key, hash);
2016         if (entry == null) {
2017           boolean created = false;
2018           segment.lock();
2019           try {
2020             // Try again--an entry could have materialized in the interim.
2021             entry = segment.getEntry(key, hash);
2022             if (entry == null) {
2023               // Create a new entry.
2024               created = true;
2025               int count = segment.count;
2026               if (count++ > segment.threshold) { // ensure capacity
2027                 segment.expand();
2028               }
2029               AtomicReferenceArray<E> table = segment.table;
2030               int index = hash & (table.length() - 1);
2031               E first = table.get(index);
2032               ++segment.modCount;
2033               entry = computingStrategy.newEntry(key, hash, first);
2034               table.set(index, entry);
2035               segment.count = count; // write-volatile
2036             }
2037           } finally {
2038             segment.unlock();
2039           }
2040 
2041           if (created) {
2042             // This thread solely created the entry.
2043             boolean success = false;
2044             try {
2045               V value = computingStrategy.compute(key, entry, computer);
2046               if (value == null) {
2047                 throw new NullPointerException(
2048                     "compute() returned null unexpectedly");
2049               }
2050               success = true;
2051               return value;
2052             } finally {
2053               if (!success) {
2054                 segment.removeEntry(entry, hash);
2055               }
2056             }
2057           }
2058         }
2059 
2060         // The entry already exists. Wait for the computation.
2061         boolean interrupted = false;
2062         try {
2063           while (true) {
2064             try {
2065               V value = computingStrategy.waitForValue(entry);
2066               if (value == null) {
2067                 // Purge entry and try again.
2068                 segment.removeEntry(entry, hash);
2069                 continue outer;
2070               }
2071               return value;
2072             } catch (InterruptedException e) {
2073               interrupted = true;
2074             }
2075           }
2076         } finally {
2077           if (interrupted) {
2078             Thread.currentThread().interrupt();
2079           }
2080         }
2081       }
2082     }
2083   }
2084 
2085   /**
2086    * A basic, no-frills implementation of {@code Strategy} using {@link
2087    * SimpleInternalEntry}. Intended to be subclassed to provide customized
2088    * behavior. For example, the following creates a map that uses byte arrays as
2089    * keys: <pre>   {@code
2090    *
2091    *   return new CustomConcurrentHashMap.Builder().buildMap(
2092    *       new SimpleStrategy<byte[], V>() {
2093    *         public int hashKey(Object key) {
2094    *           return Arrays.hashCode((byte[]) key);
2095    *         }
2096    *         public boolean equalKeys(byte[] a, Object b) {
2097    *           return Arrays.equals(a, (byte[]) b);
2098    *         }
2099    *       });}</pre>
2100    *
2101    * With nothing overridden, it yields map behavior equivalent to that of
2102    * {@link ConcurrentHashMap}.
2103    */
2104   static class SimpleStrategy<K, V>
2105       implements Strategy<K, V, SimpleInternalEntry<K, V>> {
newEntry( K key, int hash, SimpleInternalEntry<K, V> next)2106     public SimpleInternalEntry<K, V> newEntry(
2107         K key, int hash, SimpleInternalEntry<K, V> next) {
2108       return new SimpleInternalEntry<K, V>(key, hash, null, next);
2109     }
copyEntry(K key, SimpleInternalEntry<K, V> original, SimpleInternalEntry<K, V> next)2110     public SimpleInternalEntry<K, V> copyEntry(K key,
2111         SimpleInternalEntry<K, V> original, SimpleInternalEntry<K, V> next) {
2112       return new SimpleInternalEntry<K, V>(
2113           key, original.hash, original.value, next);
2114     }
setValue(SimpleInternalEntry<K, V> entry, V value)2115     public void setValue(SimpleInternalEntry<K, V> entry, V value) {
2116       entry.value = value;
2117     }
getValue(SimpleInternalEntry<K, V> entry)2118     public V getValue(SimpleInternalEntry<K, V> entry) {
2119       return entry.value;
2120     }
equalKeys(K a, Object b)2121     public boolean equalKeys(K a, Object b) {
2122       return a.equals(b);
2123     }
equalValues(V a, Object b)2124     public boolean equalValues(V a, Object b) {
2125       return a.equals(b);
2126     }
hashKey(Object key)2127     public int hashKey(Object key) {
2128       return key.hashCode();
2129     }
getKey(SimpleInternalEntry<K, V> entry)2130     public K getKey(SimpleInternalEntry<K, V> entry) {
2131       return entry.key;
2132     }
getNext(SimpleInternalEntry<K, V> entry)2133     public SimpleInternalEntry<K, V> getNext(SimpleInternalEntry<K, V> entry) {
2134       return entry.next;
2135     }
getHash(SimpleInternalEntry<K, V> entry)2136     public int getHash(SimpleInternalEntry<K, V> entry) {
2137       return entry.hash;
2138     }
setInternals( Internals<K, V, SimpleInternalEntry<K, V>> internals)2139     public void setInternals(
2140         Internals<K, V, SimpleInternalEntry<K, V>> internals) {
2141       // ignore?
2142     }
2143   }
2144 
2145   /**
2146    * A basic, no-frills entry class used by {@link SimpleInternalEntry}.
2147    */
2148   static class SimpleInternalEntry<K, V> {
2149     final K key;
2150     final int hash;
2151     final SimpleInternalEntry<K, V> next;
2152     volatile V value;
SimpleInternalEntry( K key, int hash, @Nullable V value, SimpleInternalEntry<K, V> next)2153     SimpleInternalEntry(
2154         K key, int hash, @Nullable V value, SimpleInternalEntry<K, V> next) {
2155       this.key = key;
2156       this.hash = hash;
2157       this.value = value;
2158       this.next = next;
2159     }
2160   }
2161 }
2162