ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
Revision: 1.4
Committed: Tue Aug 30 07:23:35 2011 UTC (12 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.3: +11 -9 lines
Log Message:
whitespace

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/publicdomain/zero/1.0/
5     */
6    
7     package jsr166e;
8     import jsr166e.LongAdder;
9     import java.util.Map;
10     import java.util.Set;
11     import java.util.Collection;
12     import java.util.AbstractMap;
13     import java.util.AbstractSet;
14     import java.util.AbstractCollection;
15     import java.util.Hashtable;
16     import java.util.HashMap;
17     import java.util.Iterator;
18     import java.util.Enumeration;
19     import java.util.ConcurrentModificationException;
20     import java.util.NoSuchElementException;
21     import java.util.concurrent.ConcurrentMap;
22     import java.io.Serializable;
23    
24     /**
25     * A hash table supporting full concurrency of retrievals and
26     * high expected concurrency for updates. This class obeys the
27     * same functional specification as {@link java.util.Hashtable}, and
28     * includes versions of methods corresponding to each method of
29     * {@code Hashtable}. However, even though all operations are
30     * thread-safe, retrieval operations do <em>not</em> entail locking,
31     * and there is <em>not</em> any support for locking the entire table
32     * in a way that prevents all access. This class is fully
33     * interoperable with {@code Hashtable} in programs that rely on its
34     * thread safety but not on its synchronization details.
35     *
36     * <p> Retrieval operations (including {@code get}) generally do not
37     * block, so may overlap with update operations (including {@code put}
38     * and {@code remove}). Retrievals reflect the results of the most
39     * recently <em>completed</em> update operations holding upon their
40     * onset. For aggregate operations such as {@code putAll} and {@code
41     * clear}, concurrent retrievals may reflect insertion or removal of
42     * only some entries. Similarly, Iterators and Enumerations return
43     * elements reflecting the state of the hash table at some point at or
44     * since the creation of the iterator/enumeration. They do
45     * <em>not</em> throw {@link ConcurrentModificationException}.
46     * However, iterators are designed to be used by only one thread at a
47     * time. Bear in mind that the results of aggregate status methods
48     * including {@code size}, {@code isEmpty}, and {@code containsValue}
49     * are typically useful only when a map is not undergoing concurrent
50     * updates in other threads. Otherwise the results of these methods
51     * reflect transient states that may be adequate for monitoring
52     * purposes, but not for program control.
53     *
54     * <p> Resizing this or any other kind of hash table is a relatively
55     * slow operation, so, when possible, it is a good idea to provide
56     * estimates of expected table sizes in constructors. Also, for
57     * compatability with previous versions of this class, constructors
58     * may optionally specify an expected {@code concurrencyLevel} as an
59     * additional hint for internal sizing.
60     *
61     * <p>This class and its views and iterators implement all of the
62     * <em>optional</em> methods of the {@link Map} and {@link Iterator}
63     * interfaces.
64     *
65     * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
66     * does <em>not</em> allow {@code null} to be used as a key or value.
67     *
68     * <p>This class is a member of the
69     * <a href="{@docRoot}/../technotes/guides/collections/index.html">
70     * Java Collections Framework</a>.
71     *
72     * <p><em>jsr166e note: This class is a candidate replacement for
73     * java.util.concurrent.ConcurrentHashMap.<em>
74     *
75     * @since 1.5
76     * @author Doug Lea
77     * @param <K> the type of keys maintained by this map
78     * @param <V> the type of mapped values
79     */
80     public class ConcurrentHashMapV8<K, V>
81     implements ConcurrentMap<K, V>, Serializable {
82     private static final long serialVersionUID = 7249069246763182397L;
83    
84     /**
85     * A function computing a mapping from the given key to a value,
86     * or <code>null</code> if there is no mapping. This is a
87     * place-holder for an upcoming JDK8 interface.
88     */
89     public static interface MappingFunction<K, V> {
90     /**
91     * Returns a value for the given key, or null if there is no
92     * mapping. If this function throws an (unchecked) exception,
93     * the exception is rethrown to its caller, and no mapping is
94     * recorded. Because this function is invoked within
95     * atomicity control, the computation should be short and
96     * simple. The most common usage is to construct a new object
97     * serving as an initial mapped value.
98     *
99     * @param key the (non-null) key
100     * @return a value, or null if none
101     */
102     V map(K key);
103     }
104    
105     /*
106     * Overview:
107     *
108     * The primary design goal of this hash table is to maintain
109     * concurrent readability (typically method get(), but also
110     * iterators and related methods) while minimizing update
111     * contention.
112     *
113     * Each key-value mapping is held in a Node. Because Node fields
114     * can contain special values, they are defined using plain Object
115     * types. Similarly in turn, all internal methods that use them
116     * work off Object types. All public generic-typed methods relay
117     * in/out of these internal methods, supplying casts as needed.
118     *
119     * The table is lazily initialized to a power-of-two size upon the
120     * first insertion. Each bin in the table contains a (typically
121     * short) list of Nodes. Table accesses require volatile/atomic
122     * reads, writes, and CASes. Because there is no other way to
123     * arrange this without adding further indirections, we use
124     * intrinsics (sun.misc.Unsafe) operations. The lists of nodes
125     * within bins are always accurately traversable under volatile
126     * reads, so long as lookups check hash code and non-nullness of
127     * key and value before checking key equality. (All valid hash
128 dl 1.2 * codes are nonnegative. Negative values are reserved for special
129     * forwarding nodes; see below.)
130 dl 1.1 *
131     * A bin may be locked during update (insert, delete, and replace)
132     * operations. We do not want to waste the space required to
133     * associate a distinct lock object with each bin, so instead use
134     * the first node of a bin list itself as a lock, using builtin
135     * "synchronized" locks. These save space and we can live with
136     * only plain block-structured lock/unlock operations. Using the
137     * first node of a list as a lock does not by itself suffice
138     * though: When a node is locked, any update must first validate
139     * that it is still the first node, and retry if not. (Because new
140     * nodes are always appended to lists, once a node is first in a
141     * bin, it remains first until deleted or the bin becomes
142     * invalidated.) However, update operations can and usually do
143     * still traverse the bin until the point of update, which helps
144     * reduce cache misses on retries. This is a converse of sorts to
145     * the lazy locking technique described by Herlihy & Shavit. If
146     * there is no existing node during a put operation, then one can
147     * be CAS'ed in (without need for lock except in computeIfAbsent);
148     * the CAS serves as validation. This is on average the most
149     * common case for put operations. The expected number of locks
150     * covering different elements (i.e., bins with 2 or more nodes)
151     * is approximately 10% at steady state under default settings.
152     * Lock contention probability for two threads accessing arbitrary
153     * distinct elements is thus less than 1% even for small tables.
154     *
155     * The table is resized when occupancy exceeds a threshold. Only
156     * a single thread performs the resize (using field "resizing", to
157     * arrange exclusion), but the table otherwise remains usable for
158     * both reads and updates. Resizing proceeds by transferring bins,
159     * one by one, from the table to the next table. Upon transfer,
160     * the old table bin contains only a special forwarding node (with
161     * negative hash code ("MOVED")) that contains the next table as
162     * its key. On encountering a forwarding node, access and update
163     * operations restart, using the new table. To ensure concurrent
164     * readability of traversals, transfers must proceed from the last
165     * bin (table.length - 1) up towards the first. Any traversal
166     * starting from the first bin can then arrange to move to the new
167     * table for the rest of the traversal without revisiting nodes.
168     * This constrains bin transfers to a particular order, and so can
169     * block indefinitely waiting for the next lock, and other threads
170     * cannot help with the transfer. However, expected stalls are
171     * infrequent enough to not warrant the additional overhead and
172     * complexity of access and iteration schemes that could admit
173     * out-of-order or concurrent bin transfers.
174     *
175 dl 1.2 * A similar traversal scheme (not yet implemented) can apply to
176     * partial traversals during partitioned aggregate operations.
177     * Also, read-only operations give up if ever forwarded to a null
178     * table, which provides support for shutdown-style clearing,
179     * which is also not currently implemented.
180 dl 1.1 *
181     * The element count is maintained using a LongAdder, which avoids
182     * contention on updates but can encounter cache thrashing if read
183     * too frequently during concurrent updates. To avoid reading so
184 dl 1.2 * often, resizing is normally attempted only upon adding to a bin
185     * already holding two or more nodes. Under the default threshold
186     * (0.75), and uniform hash distributions, the probability of this
187 dl 1.1 * occurring at threshold is around 13%, meaning that only about 1
188     * in 8 puts check threshold (and after resizing, many fewer do
189 dl 1.2 * so). But this approximation has high variance for small table
190     * sizes, so we check on any collision for sizes <= 64. Further,
191     * to increase the probablity that a resize occurs soon enough, we
192     * offset the threshold (see THRESHOLD_OFFSET) by the expected
193     * number of puts between checks. This is currently set to 8, in
194     * accord with the default load factor. In practice, this is
195     * rarely overridden, and in any case is close enough to other
196 dl 1.1 * plausible values not to waste dynamic probablity computation
197     * for more precision.
198     */
199    
200     /* ---------------- Constants -------------- */
201    
202     /**
203     * The smallest allowed table capacity. Must be a power of 2, at
204     * least 2.
205     */
206     static final int MINIMUM_CAPACITY = 2;
207    
208     /**
209     * The largest allowed table capacity. Must be a power of 2, at
210     * most 1<<30.
211     */
212     static final int MAXIMUM_CAPACITY = 1 << 30;
213    
214     /**
215     * The default initial table capacity. Must be a power of 2, at
216     * least MINIMUM_CAPACITY and at most MAXIMUM_CAPACITY
217     */
218     static final int DEFAULT_CAPACITY = 16;
219    
220     /**
221     * The default load factor for this table, used when not otherwise
222     * specified in a constructor.
223     */
224     static final float DEFAULT_LOAD_FACTOR = 0.75f;
225    
226     /**
227     * The default concurrency level for this table. Unused, but
228     * defined for compatibility with previous versions of this class.
229     */
230     static final int DEFAULT_CONCURRENCY_LEVEL = 16;
231    
232     /**
233     * The count value to offset thesholds to compensate for checking
234     * for resizing only when inserting into bins with two or more
235     * elements. See above for explanation.
236     */
237     static final int THRESHOLD_OFFSET = 8;
238    
239     /**
240     * Special node hash value indicating to use table in node.key
241     * Must be negative.
242     */
243     static final int MOVED = -1;
244    
245     /* ---------------- Fields -------------- */
246    
247     /**
248     * The array of bins. Lazily initialized upon first insertion.
249     * Size is always a power of two. Accessed directly by inner
250     * classes.
251     */
252     transient volatile Node[] table;
253    
254     /** The counter maintaining number of elements. */
255     private transient final LongAdder counter;
256     /** Nonzero when table is being initialized or resized. Updated via CAS. */
257     private transient volatile int resizing;
258     /** The target load factor for the table. */
259     private transient float loadFactor;
260     /** The next element count value upon which to resize the table. */
261     private transient int threshold;
262     /** The initial capacity of the table. */
263     private transient int initCap;
264    
265     // views
266     transient Set<K> keySet;
267     transient Set<Map.Entry<K,V>> entrySet;
268     transient Collection<V> values;
269    
270     /** For serialization compatability. Null unless serialized; see below */
271     Segment<K,V>[] segments;
272    
273     /**
274     * Applies a supplemental hash function to a given hashCode, which
275     * defends against poor quality hash functions. The result must
276     * be non-negative, and for reasonable performance must have good
277     * avalanche properties; i.e., that each bit of the argument
278     * affects each bit (except sign bit) of the result.
279     */
280     private static final int spread(int h) {
281     // Apply base step of MurmurHash; see http://code.google.com/p/smhasher/
282     h ^= h >>> 16;
283     h *= 0x85ebca6b;
284     h ^= h >>> 13;
285     h *= 0xc2b2ae35;
286     return (h >>> 16) ^ (h & 0x7fffffff); // mask out sign bit
287     }
288    
289     /**
290     * Key-value entry. Note that this is never exported out as a
291     * user-visible Map.Entry.
292     */
293     static final class Node {
294     final int hash;
295     final Object key;
296     volatile Object val;
297     volatile Node next;
298    
299     Node(int hash, Object key, Object val, Node next) {
300     this.hash = hash;
301     this.key = key;
302     this.val = val;
303     this.next = next;
304     }
305     }
306    
307     /*
308     * Volatile access nethods are used for table elements as well as
309     * elements of in-progress next table while resizing. Uses in
310     * access and update methods are null checked by callers, and
311     * implicitly bounds-checked, relying on the invariants that tab
312     * arrays have non-zero size, and all indices are masked with
313     * (tab.length - 1) which is never negative and always less than
314 dl 1.2 * length. The "relaxed" non-volatile forms are used only during
315     * table initialization. The only other usage is in
316     * HashIterator.advance, which performs explicit checks.
317 dl 1.1 */
318    
319     static final Node tabAt(Node[] tab, int i) { // used in HashIterator
320     return (Node)UNSAFE.getObjectVolatile(tab, ((long)i<<ASHIFT)+ABASE);
321     }
322    
323     private static final boolean casTabAt(Node[] tab, int i, Node c, Node v) {
324     return UNSAFE.compareAndSwapObject(tab, ((long)i<<ASHIFT)+ABASE, c, v);
325     }
326    
327     private static final void setTabAt(Node[] tab, int i, Node v) {
328     UNSAFE.putObjectVolatile(tab, ((long)i<<ASHIFT)+ABASE, v);
329     }
330    
331 dl 1.2 private static final Node relaxedTabAt(Node[] tab, int i) {
332     return (Node)UNSAFE.getObject(tab, ((long)i<<ASHIFT)+ABASE);
333     }
334    
335     private static final void relaxedSetTabAt(Node[] tab, int i, Node v) {
336     UNSAFE.putObject(tab, ((long)i<<ASHIFT)+ABASE, v);
337     }
338    
339 dl 1.1 /* ---------------- Access and update operations -------------- */
340    
341 dl 1.2 /** Implementation for get and containsKey **/
342 jsr166 1.4 private final Object internalGet(Object k) {
343 dl 1.1 int h = spread(k.hashCode());
344     Node[] tab = table;
345     retry: while (tab != null) {
346     Node e = tabAt(tab, (tab.length - 1) & h);
347     while (e != null) {
348     int eh = e.hash;
349     if (eh == h) {
350     Object ek = e.key, ev = e.val;
351     if (ev != null && ek != null && (k == ek || k.equals(ek)))
352     return ev;
353     }
354 dl 1.2 else if (eh < 0) { // bin was moved during resize
355 dl 1.1 tab = (Node[])e.key;
356     continue retry;
357     }
358     e = e.next;
359     }
360     break;
361     }
362     return null;
363     }
364    
365 dl 1.2 /** Implementation for put and putIfAbsent **/
366 dl 1.1 private final Object internalPut(Object k, Object v, boolean replace) {
367     int h = spread(k.hashCode());
368     Object oldVal = null; // the previous value or null if none
369     Node[] tab = table;
370     for (;;) {
371     Node e; int i;
372     if (tab == null)
373     tab = grow(0);
374     else if ((e = tabAt(tab, i = (tab.length - 1) & h)) == null) {
375 dl 1.2 if (casTabAt(tab, i, null, new Node(h, k, v, null)))
376 dl 1.1 break;
377     }
378     else if (e.hash < 0)
379     tab = (Node[])e.key;
380     else {
381     boolean validated = false;
382     boolean checkSize = false;
383 jsr166 1.4 synchronized (e) {
384 dl 1.1 Node first = e;
385     for (;;) {
386     Object ek, ev;
387     if ((ev = e.val) == null)
388     break;
389     if (e.hash == h && (ek = e.key) != null &&
390     (k == ek || k.equals(ek))) {
391     if (tabAt(tab, i) == first) {
392     validated = true;
393     oldVal = ev;
394     if (replace)
395     e.val = v;
396     }
397     break;
398     }
399     Node last = e;
400     if ((e = e.next) == null) {
401     if (tabAt(tab, i) == first) {
402     validated = true;
403 dl 1.2 last.next = new Node(h, k, v, null);
404     if (last != first || tab.length <= 64)
405 dl 1.1 checkSize = true;
406     }
407     break;
408     }
409     }
410     }
411     if (validated) {
412     if (checkSize && tab.length < MAXIMUM_CAPACITY &&
413     resizing == 0 && counter.sum() >= threshold)
414     grow(0);
415     break;
416     }
417     }
418     }
419     if (oldVal == null)
420     counter.increment();
421     return oldVal;
422     }
423    
424     /**
425     * Covers the four public remove/replace methods: Replaces node
426     * value with v, conditional upon match of cv if non-null. If
427     * resulting value is null, delete.
428     */
429     private final Object internalReplace(Object k, Object v, Object cv) {
430     int h = spread(k.hashCode());
431     Object oldVal = null;
432     Node e; int i;
433     Node[] tab = table;
434     while (tab != null &&
435     (e = tabAt(tab, i = (tab.length - 1) & h)) != null) {
436     if (e.hash < 0)
437     tab = (Node[])e.key;
438     else {
439     boolean validated = false;
440     boolean deleted = false;
441 jsr166 1.4 synchronized (e) {
442 dl 1.1 Node pred = null;
443     Node first = e;
444     for (;;) {
445     Object ek, ev;
446     if ((ev = e.val) == null)
447     break;
448     if (e.hash == h && (ek = e.key) != null &&
449     (k == ek || k.equals(ek))) {
450     if (tabAt(tab, i) == first) {
451     validated = true;
452     if (cv == null || cv == ev || cv.equals(ev)) {
453     oldVal = ev;
454     if ((e.val = v) == null) {
455     deleted = true;
456     Node en = e.next;
457     if (pred != null)
458     pred.next = en;
459     else
460     setTabAt(tab, i, en);
461     }
462     }
463     }
464     break;
465     }
466     pred = e;
467     if ((e = e.next) == null) {
468     if (tabAt(tab, i) == first)
469     validated = true;
470     break;
471     }
472     }
473     }
474     if (validated) {
475     if (deleted)
476     counter.decrement();
477     break;
478     }
479     }
480     }
481     return oldVal;
482     }
483    
484 dl 1.2 /** Implementation for computeIfAbsent and compute */
485 dl 1.1 @SuppressWarnings("unchecked")
486 dl 1.2 private final V internalCompute(K k,
487     MappingFunction<? super K, ? extends V> f,
488     boolean replace) {
489 dl 1.1 int h = spread(k.hashCode());
490     V val = null;
491     boolean added = false;
492     boolean validated = false;
493     Node[] tab = table;
494     do {
495     Node e; int i;
496     if (tab == null)
497     tab = grow(0);
498     else if ((e = tabAt(tab, i = (tab.length - 1) & h)) == null) {
499 dl 1.2 Node node = new Node(h, k, null, null);
500 jsr166 1.4 synchronized (node) {
501 dl 1.1 if (casTabAt(tab, i, null, node)) {
502     validated = true;
503     try {
504     val = f.map(k);
505     if (val != null) {
506     node.val = val;
507     added = true;
508     }
509     } finally {
510     if (!added)
511     setTabAt(tab, i, null);
512     }
513     }
514     }
515     }
516     else if (e.hash < 0)
517     tab = (Node[])e.key;
518     else {
519     boolean checkSize = false;
520 jsr166 1.4 synchronized (e) {
521 dl 1.1 Node first = e;
522     for (;;) {
523     Object ek, ev;
524     if ((ev = e.val) == null)
525     break;
526     if (e.hash == h && (ek = e.key) != null &&
527     (k == ek || k.equals(ek))) {
528     if (tabAt(tab, i) == first) {
529     validated = true;
530 dl 1.2 if (replace && (ev = f.map(k)) != null)
531     e.val = ev;
532 dl 1.1 val = (V)ev;
533     }
534     break;
535     }
536     Node last = e;
537     if ((e = e.next) == null) {
538     if (tabAt(tab, i) == first) {
539     validated = true;
540     if ((val = f.map(k)) != null) {
541 dl 1.2 last.next = new Node(h, k, val, null);
542     added = true;
543     if (last != first || tab.length <= 64)
544 dl 1.1 checkSize = true;
545     }
546     }
547     break;
548     }
549     }
550     }
551     if (checkSize && tab.length < MAXIMUM_CAPACITY &&
552     resizing == 0 && counter.sum() >= threshold)
553     grow(0);
554     }
555     } while (!validated);
556     if (added)
557     counter.increment();
558     return val;
559     }
560    
561     /*
562     * Reclassifies nodes in each bin to new table. Because we are
563     * using power-of-two expansion, the elements from each bin must
564     * either stay at same index, or move with a power of two
565     * offset. We eliminate unnecessary node creation by catching
566     * cases where old nodes can be reused because their next fields
567     * won't change. Statistically, at the default threshold, only
568     * about one-sixth of them need cloning when a table doubles. The
569     * nodes they replace will be garbage collectable as soon as they
570     * are no longer referenced by any reader thread that may be in
571     * the midst of concurrently traversing table.
572     *
573     * Transfers are done from the bottom up to preserve iterator
574     * traversability. On each step, the old bin is locked,
575     * moved/copied, and then replaced with a forwarding node.
576     */
577     private static final void transfer(Node[] tab, Node[] nextTab) {
578     int n = tab.length;
579     int mask = nextTab.length - 1;
580     Node fwd = new Node(MOVED, nextTab, null, null);
581     for (int i = n - 1; i >= 0; --i) {
582     for (Node e;;) {
583     if ((e = tabAt(tab, i)) == null) {
584     if (casTabAt(tab, i, e, fwd))
585     break;
586     }
587     else {
588     boolean validated = false;
589 jsr166 1.4 synchronized (e) {
590 dl 1.1 int idx = e.hash & mask;
591     Node lastRun = e;
592     for (Node p = e.next; p != null; p = p.next) {
593     int j = p.hash & mask;
594     if (j != idx) {
595     idx = j;
596     lastRun = p;
597     }
598     }
599     if (tabAt(tab, i) == e) {
600     validated = true;
601 dl 1.2 relaxedSetTabAt(nextTab, idx, lastRun);
602 dl 1.1 for (Node p = e; p != lastRun; p = p.next) {
603     int h = p.hash;
604     int j = h & mask;
605 dl 1.2 Node r = relaxedTabAt(nextTab, j);
606     relaxedSetTabAt(nextTab, j,
607     new Node(h, p.key, p.val, r));
608 dl 1.1 }
609     setTabAt(tab, i, fwd);
610     }
611     }
612     if (validated)
613     break;
614     }
615     }
616     }
617     }
618    
619     /**
620     * If not already resizing, initializes or creates next table and
621     * transfers bins. Rechecks occupancy after a transfer to see if
622     * another resize is already needed because resizings are lagging
623     * additions.
624     *
625     * @param sizeHint overridden capacity target (nonzero only from putAll)
626     * @return current table
627     */
628     private final Node[] grow(int sizeHint) {
629     if (resizing == 0 &&
630     UNSAFE.compareAndSwapInt(this, resizingOffset, 0, 1)) {
631     try {
632     for (;;) {
633     int cap, n;
634 dl 1.2 Node[] tab = table;
635     if (tab == null) {
636 dl 1.1 int c = initCap;
637     if (c < sizeHint)
638     c = sizeHint;
639     if (c == DEFAULT_CAPACITY)
640     cap = c;
641     else if (c >= MAXIMUM_CAPACITY)
642     cap = MAXIMUM_CAPACITY;
643     else {
644     cap = MINIMUM_CAPACITY;
645     while (cap < c)
646     cap <<= 1;
647     }
648     }
649     else if ((n = tab.length) < MAXIMUM_CAPACITY &&
650     (sizeHint <= 0 || n < sizeHint))
651     cap = n << 1;
652     else
653     break;
654     threshold = (int)(cap * loadFactor) - THRESHOLD_OFFSET;
655     Node[] nextTab = new Node[cap];
656     if (tab != null)
657     transfer(tab, nextTab);
658     table = nextTab;
659 dl 1.2 if (tab == null || cap >= MAXIMUM_CAPACITY ||
660     (sizeHint > 0 && cap >= sizeHint) ||
661     counter.sum() < threshold)
662 dl 1.1 break;
663     }
664     } finally {
665     resizing = 0;
666     }
667     }
668 dl 1.2 else if (table == null)
669 dl 1.1 Thread.yield(); // lost initialization race; just spin
670 dl 1.2 return table;
671 dl 1.1 }
672    
673     /**
674 dl 1.2 * Implementation for putAll and constructor with Map
675     * argument. Tries to first override initial capacity or grow
676     * based on map size to pre-allocate table space.
677 dl 1.1 */
678     private final void internalPutAll(Map<? extends K, ? extends V> m) {
679     int s = m.size();
680 jsr166 1.4 grow((s >= (MAXIMUM_CAPACITY >>> 1)) ? s : s + (s >>> 1));
681 dl 1.1 for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
682     Object k = e.getKey();
683     Object v = e.getValue();
684     if (k == null || v == null)
685     throw new NullPointerException();
686     internalPut(k, v, true);
687     }
688     }
689    
690     /**
691 dl 1.2 * Implementation for clear. Steps through each bin, removing all nodes.
692 dl 1.1 */
693     private final void internalClear() {
694 dl 1.2 long deletions = 0L;
695 dl 1.1 int i = 0;
696     Node[] tab = table;
697     while (tab != null && i < tab.length) {
698     Node e = tabAt(tab, i);
699     if (e == null)
700     ++i;
701     else if (e.hash < 0)
702     tab = (Node[])e.key;
703     else {
704     boolean validated = false;
705 jsr166 1.4 synchronized (e) {
706 dl 1.1 if (tabAt(tab, i) == e) {
707     validated = true;
708     do {
709     if (e.val != null) {
710     e.val = null;
711 dl 1.2 ++deletions;
712 dl 1.1 }
713     } while ((e = e.next) != null);
714     setTabAt(tab, i, null);
715     }
716     }
717 dl 1.2 if (validated) {
718 dl 1.1 ++i;
719 dl 1.2 if (deletions > THRESHOLD_OFFSET) { // bound lag in counts
720     counter.add(-deletions);
721     deletions = 0L;
722     }
723     }
724 dl 1.1 }
725     }
726 dl 1.2 if (deletions != 0L)
727     counter.add(-deletions);
728 dl 1.1 }
729    
730     /**
731     * Base class for key, value, and entry iterators, plus internal
732     * implementations of public traversal-based methods, to avoid
733     * duplicating traversal code.
734     */
735     class HashIterator {
736     private Node next; // the next entry to return
737     private Node[] tab; // current table; updated if resized
738     private Node lastReturned; // the last entry returned, for remove
739     private Object nextVal; // cached value of next
740     private int index; // index of bin to use next
741     private int baseIndex; // current index of initial table
742     private final int baseSize; // initial table size
743    
744     HashIterator() {
745     Node[] t = tab = table;
746     if (t == null)
747     baseSize = 0;
748     else {
749     baseSize = t.length;
750     advance(null);
751     }
752     }
753    
754     public final boolean hasNext() { return next != null; }
755     public final boolean hasMoreElements() { return next != null; }
756    
757     /**
758     * Advances next. Normally, iteration proceeds bin-by-bin
759     * traversing lists. However, if the table has been resized,
760     * then all future steps must traverse both the bin at the
761     * current index as well as at (index + baseSize); and so on
762     * for further resizings. To paranoically cope with potential
763     * (improper) sharing of iterators across threads, table reads
764     * are bounds-checked.
765     */
766     final void advance(Node e) {
767     for (;;) {
768     Node[] t; int i; // for bounds checks
769     if (e != null) {
770     Object ek = e.key, ev = e.val;
771     if (ev != null && ek != null) {
772     nextVal = ev;
773     next = e;
774     break;
775     }
776     e = e.next;
777     }
778     else if (baseIndex < baseSize && (t = tab) != null &&
779     t.length > (i = index) && i >= 0) {
780     if ((e = tabAt(t, i)) != null && e.hash < 0) {
781     tab = (Node[])e.key;
782     e = null;
783     }
784     else if (i + baseSize < t.length)
785     index += baseSize; // visit forwarded upper slots
786     else
787     index = ++baseIndex;
788     }
789     else {
790     next = null;
791     break;
792     }
793     }
794     }
795    
796     final Object nextKey() {
797     Node e = next;
798     if (e == null)
799     throw new NoSuchElementException();
800     Object k = e.key;
801     advance((lastReturned = e).next);
802     return k;
803     }
804    
805     final Object nextValue() {
806     Node e = next;
807     if (e == null)
808     throw new NoSuchElementException();
809     Object v = nextVal;
810     advance((lastReturned = e).next);
811     return v;
812     }
813    
814     final WriteThroughEntry nextEntry() {
815     Node e = next;
816     if (e == null)
817     throw new NoSuchElementException();
818     WriteThroughEntry entry =
819     new WriteThroughEntry(e.key, nextVal);
820     advance((lastReturned = e).next);
821     return entry;
822     }
823    
824     public final void remove() {
825     if (lastReturned == null)
826     throw new IllegalStateException();
827     ConcurrentHashMapV8.this.remove(lastReturned.key);
828     lastReturned = null;
829     }
830    
831     /** Helper for serialization */
832     final void writeEntries(java.io.ObjectOutputStream s)
833     throws java.io.IOException {
834     Node e;
835     while ((e = next) != null) {
836     s.writeObject(e.key);
837     s.writeObject(nextVal);
838     advance(e.next);
839     }
840     }
841    
842     /** Helper for containsValue */
843     final boolean containsVal(Object value) {
844     if (value != null) {
845     Node e;
846     while ((e = next) != null) {
847     Object v = nextVal;
848     if (value == v || value.equals(v))
849     return true;
850     advance(e.next);
851     }
852     }
853     return false;
854     }
855    
856     /** Helper for Map.hashCode */
857     final int mapHashCode() {
858     int h = 0;
859     Node e;
860     while ((e = next) != null) {
861     h += e.key.hashCode() ^ nextVal.hashCode();
862     advance(e.next);
863     }
864     return h;
865     }
866    
867     /** Helper for Map.toString */
868     final String mapToString() {
869     Node e = next;
870     if (e == null)
871     return "{}";
872     StringBuilder sb = new StringBuilder();
873     sb.append('{');
874     for (;;) {
875     sb.append(e.key == this ? "(this Map)" : e.key);
876     sb.append('=');
877     sb.append(nextVal == this ? "(this Map)" : nextVal);
878     advance(e.next);
879     if ((e = next) != null)
880     sb.append(',').append(' ');
881     else
882     return sb.append('}').toString();
883     }
884     }
885     }
886    
887     /* ---------------- Public operations -------------- */
888    
889     /**
890     * Creates a new, empty map with the specified initial
891     * capacity, load factor and concurrency level.
892     *
893     * @param initialCapacity the initial capacity. The implementation
894     * performs internal sizing to accommodate this many elements.
895     * @param loadFactor the load factor threshold, used to control resizing.
896     * Resizing may be performed when the average number of elements per
897     * bin exceeds this threshold.
898     * @param concurrencyLevel the estimated number of concurrently
899     * updating threads. The implementation may use this value as
900     * a sizing hint.
901     * @throws IllegalArgumentException if the initial capacity is
902     * negative or the load factor or concurrencyLevel are
903     * nonpositive.
904     */
905     public ConcurrentHashMapV8(int initialCapacity,
906     float loadFactor, int concurrencyLevel) {
907     if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
908     throw new IllegalArgumentException();
909     this.initCap = initialCapacity;
910     this.loadFactor = loadFactor;
911     this.counter = new LongAdder();
912     }
913    
914     /**
915     * Creates a new, empty map with the specified initial capacity
916     * and load factor and with the default concurrencyLevel (16).
917     *
918     * @param initialCapacity The implementation performs internal
919     * sizing to accommodate this many elements.
920     * @param loadFactor the load factor threshold, used to control resizing.
921     * Resizing may be performed when the average number of elements per
922     * bin exceeds this threshold.
923     * @throws IllegalArgumentException if the initial capacity of
924     * elements is negative or the load factor is nonpositive
925     *
926     * @since 1.6
927     */
928     public ConcurrentHashMapV8(int initialCapacity, float loadFactor) {
929     this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
930     }
931    
932     /**
933     * Creates a new, empty map with the specified initial capacity,
934     * and with default load factor (0.75) and concurrencyLevel (16).
935     *
936     * @param initialCapacity the initial capacity. The implementation
937     * performs internal sizing to accommodate this many elements.
938     * @throws IllegalArgumentException if the initial capacity of
939     * elements is negative.
940     */
941     public ConcurrentHashMapV8(int initialCapacity) {
942     this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
943     }
944    
945     /**
946     * Creates a new, empty map with a default initial capacity (16),
947     * load factor (0.75) and concurrencyLevel (16).
948     */
949     public ConcurrentHashMapV8() {
950     this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
951     }
952    
953     /**
954     * Creates a new map with the same mappings as the given map.
955     * The map is created with a capacity of 1.5 times the number
956     * of mappings in the given map or 16 (whichever is greater),
957     * and a default load factor (0.75) and concurrencyLevel (16).
958     *
959     * @param m the map
960     */
961     public ConcurrentHashMapV8(Map<? extends K, ? extends V> m) {
962     this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
963     if (m == null)
964     throw new NullPointerException();
965     internalPutAll(m);
966     }
967    
968     /**
969     * Returns {@code true} if this map contains no key-value mappings.
970     *
971     * @return {@code true} if this map contains no key-value mappings
972     */
973     public boolean isEmpty() {
974 dl 1.2 return counter.sum() <= 0L; // ignore transient negative values
975 dl 1.1 }
976    
977     /**
978     * Returns the number of key-value mappings in this map. If the
979     * map contains more than {@code Integer.MAX_VALUE} elements, returns
980     * {@code Integer.MAX_VALUE}.
981     *
982     * @return the number of key-value mappings in this map
983     */
984     public int size() {
985     long n = counter.sum();
986 jsr166 1.4 return (n <= 0L) ? 0 :
987     (n >= Integer.MAX_VALUE) ? Integer.MAX_VALUE :
988     (int)n;
989 dl 1.1 }
990    
991     /**
992     * Returns the value to which the specified key is mapped,
993     * or {@code null} if this map contains no mapping for the key.
994     *
995     * <p>More formally, if this map contains a mapping from a key
996     * {@code k} to a value {@code v} such that {@code key.equals(k)},
997     * then this method returns {@code v}; otherwise it returns
998     * {@code null}. (There can be at most one such mapping.)
999     *
1000     * @throws NullPointerException if the specified key is null
1001     */
1002     @SuppressWarnings("unchecked")
1003     public V get(Object key) {
1004     if (key == null)
1005     throw new NullPointerException();
1006     return (V)internalGet(key);
1007     }
1008    
1009     /**
1010     * Tests if the specified object is a key in this table.
1011     *
1012     * @param key possible key
1013     * @return {@code true} if and only if the specified object
1014     * is a key in this table, as determined by the
1015     * {@code equals} method; {@code false} otherwise.
1016     * @throws NullPointerException if the specified key is null
1017     */
1018     public boolean containsKey(Object key) {
1019     if (key == null)
1020     throw new NullPointerException();
1021     return internalGet(key) != null;
1022     }
1023    
1024     /**
1025     * Returns {@code true} if this map maps one or more keys to the
1026     * specified value. Note: This method requires a full internal
1027     * traversal of the hash table, and so is much slower than
1028     * method {@code containsKey}.
1029     *
1030     * @param value value whose presence in this map is to be tested
1031     * @return {@code true} if this map maps one or more keys to the
1032     * specified value
1033     * @throws NullPointerException if the specified value is null
1034     */
1035     public boolean containsValue(Object value) {
1036     if (value == null)
1037     throw new NullPointerException();
1038     return new HashIterator().containsVal(value);
1039     }
1040    
1041     /**
1042     * Legacy method testing if some key maps into the specified value
1043     * in this table. This method is identical in functionality to
1044     * {@link #containsValue}, and exists solely to ensure
1045     * full compatibility with class {@link java.util.Hashtable},
1046     * which supported this method prior to introduction of the
1047     * Java Collections framework.
1048     *
1049     * @param value a value to search for
1050     * @return {@code true} if and only if some key maps to the
1051     * {@code value} argument in this table as
1052     * determined by the {@code equals} method;
1053     * {@code false} otherwise
1054     * @throws NullPointerException if the specified value is null
1055     */
1056     public boolean contains(Object value) {
1057     return containsValue(value);
1058     }
1059    
1060     /**
1061     * Maps the specified key to the specified value in this table.
1062     * Neither the key nor the value can be null.
1063     *
1064     * <p> The value can be retrieved by calling the {@code get} method
1065     * with a key that is equal to the original key.
1066     *
1067     * @param key key with which the specified value is to be associated
1068     * @param value value to be associated with the specified key
1069     * @return the previous value associated with {@code key}, or
1070     * {@code null} if there was no mapping for {@code key}
1071     * @throws NullPointerException if the specified key or value is null
1072     */
1073     @SuppressWarnings("unchecked")
1074     public V put(K key, V value) {
1075     if (key == null || value == null)
1076     throw new NullPointerException();
1077     return (V)internalPut(key, value, true);
1078     }
1079    
1080     /**
1081     * {@inheritDoc}
1082     *
1083     * @return the previous value associated with the specified key,
1084     * or {@code null} if there was no mapping for the key
1085     * @throws NullPointerException if the specified key or value is null
1086     */
1087     @SuppressWarnings("unchecked")
1088     public V putIfAbsent(K key, V value) {
1089     if (key == null || value == null)
1090     throw new NullPointerException();
1091     return (V)internalPut(key, value, false);
1092     }
1093    
1094     /**
1095     * Copies all of the mappings from the specified map to this one.
1096     * These mappings replace any mappings that this map had for any of the
1097     * keys currently in the specified map.
1098     *
1099     * @param m mappings to be stored in this map
1100     */
1101     public void putAll(Map<? extends K, ? extends V> m) {
1102     if (m == null)
1103     throw new NullPointerException();
1104     internalPutAll(m);
1105     }
1106    
1107     /**
1108     * If the specified key is not already associated with a value,
1109     * computes its value using the given mappingFunction, and if
1110     * non-null, enters it into the map. This is equivalent to
1111     *
1112     * <pre>
1113     * if (map.containsKey(key))
1114     * return map.get(key);
1115     * value = mappingFunction.map(key);
1116     * if (value != null)
1117 dl 1.2 * map.put(key, value);
1118     * return value;
1119 dl 1.1 * </pre>
1120     *
1121     * except that the action is performed atomically. Some attempted
1122     * operations on this map by other threads may be blocked while
1123 dl 1.2 * computation is in progress, so the computation should be short
1124     * and simple, and must not attempt to update any other mappings
1125     * of this Map. The most common usage is to construct a new object
1126 dl 1.1 * serving as an initial mapped value, or memoized result.
1127     *
1128     * @param key key with which the specified value is to be associated
1129     * @param mappingFunction the function to compute a value
1130     * @return the current (existing or computed) value associated with
1131     * the specified key, or {@code null} if the computation
1132     * returned {@code null}.
1133     * @throws NullPointerException if the specified key or mappingFunction
1134     * is null,
1135     * @throws RuntimeException or Error if the mappingFunction does so,
1136     * in which case the mapping is left unestablished.
1137     */
1138     public V computeIfAbsent(K key, MappingFunction<? super K, ? extends V> mappingFunction) {
1139     if (key == null || mappingFunction == null)
1140     throw new NullPointerException();
1141 dl 1.2 return internalCompute(key, mappingFunction, false);
1142     }
1143    
1144     /**
1145     * Computes the value associated with he given key using the given
1146     * mappingFunction, and if non-null, enters it into the map. This
1147     * is equivalent to
1148     *
1149     * <pre>
1150     * value = mappingFunction.map(key);
1151     * if (value != null)
1152     * map.put(key, value);
1153     * else
1154     * return map.get(key);
1155     * </pre>
1156     *
1157     * except that the action is performed atomically. Some attempted
1158     * operations on this map by other threads may be blocked while
1159     * computation is in progress, so the computation should be short
1160     * and simple, and must not attempt to update any other mappings
1161     * of this Map.
1162     *
1163     * @param key key with which the specified value is to be associated
1164     * @param mappingFunction the function to compute a value
1165     * @return the current value associated with
1166     * the specified key, or {@code null} if the computation
1167     * returned {@code null} and the value was not otherwise present.
1168     * @throws NullPointerException if the specified key or mappingFunction
1169     * is null,
1170     * @throws RuntimeException or Error if the mappingFunction does so,
1171     * in which case the mapping is unchanged.
1172     */
1173     public V compute(K key, MappingFunction<? super K, ? extends V> mappingFunction) {
1174     if (key == null || mappingFunction == null)
1175     throw new NullPointerException();
1176     return internalCompute(key, mappingFunction, true);
1177 dl 1.1 }
1178    
1179     /**
1180     * Removes the key (and its corresponding value) from this map.
1181     * This method does nothing if the key is not in the map.
1182     *
1183     * @param key the key that needs to be removed
1184     * @return the previous value associated with {@code key}, or
1185     * {@code null} if there was no mapping for {@code key}
1186     * @throws NullPointerException if the specified key is null
1187     */
1188     @SuppressWarnings("unchecked")
1189     public V remove(Object key) {
1190     if (key == null)
1191     throw new NullPointerException();
1192 jsr166 1.3 return (V)internalReplace(key, null, null);
1193 dl 1.1 }
1194    
1195     /**
1196     * {@inheritDoc}
1197     *
1198     * @throws NullPointerException if the specified key is null
1199     */
1200     public boolean remove(Object key, Object value) {
1201     if (key == null)
1202     throw new NullPointerException();
1203     if (value == null)
1204     return false;
1205     return internalReplace(key, null, value) != null;
1206     }
1207    
1208     /**
1209     * {@inheritDoc}
1210     *
1211     * @throws NullPointerException if any of the arguments are null
1212     */
1213     public boolean replace(K key, V oldValue, V newValue) {
1214     if (key == null || oldValue == null || newValue == null)
1215     throw new NullPointerException();
1216 jsr166 1.3 return internalReplace(key, newValue, oldValue) != null;
1217 dl 1.1 }
1218    
1219     /**
1220     * {@inheritDoc}
1221     *
1222     * @return the previous value associated with the specified key,
1223     * or {@code null} if there was no mapping for the key
1224     * @throws NullPointerException if the specified key or value is null
1225     */
1226     @SuppressWarnings("unchecked")
1227     public V replace(K key, V value) {
1228     if (key == null || value == null)
1229     throw new NullPointerException();
1230 jsr166 1.3 return (V)internalReplace(key, value, null);
1231 dl 1.1 }
1232    
1233     /**
1234     * Removes all of the mappings from this map.
1235     */
1236     public void clear() {
1237     internalClear();
1238     }
1239    
1240     /**
1241     * Returns a {@link Set} view of the keys contained in this map.
1242     * The set is backed by the map, so changes to the map are
1243     * reflected in the set, and vice-versa. The set supports element
1244     * removal, which removes the corresponding mapping from this map,
1245     * via the {@code Iterator.remove}, {@code Set.remove},
1246     * {@code removeAll}, {@code retainAll}, and {@code clear}
1247     * operations. It does not support the {@code add} or
1248     * {@code addAll} operations.
1249     *
1250     * <p>The view's {@code iterator} is a "weakly consistent" iterator
1251     * that will never throw {@link ConcurrentModificationException},
1252     * and guarantees to traverse elements as they existed upon
1253     * construction of the iterator, and may (but is not guaranteed to)
1254     * reflect any modifications subsequent to construction.
1255     */
1256     public Set<K> keySet() {
1257     Set<K> ks = keySet;
1258     return (ks != null) ? ks : (keySet = new KeySet());
1259     }
1260    
1261     /**
1262     * Returns a {@link Collection} view of the values contained in this map.
1263     * The collection is backed by the map, so changes to the map are
1264     * reflected in the collection, and vice-versa. The collection
1265     * supports element removal, which removes the corresponding
1266     * mapping from this map, via the {@code Iterator.remove},
1267     * {@code Collection.remove}, {@code removeAll},
1268     * {@code retainAll}, and {@code clear} operations. It does not
1269     * support the {@code add} or {@code addAll} operations.
1270     *
1271     * <p>The view's {@code iterator} is a "weakly consistent" iterator
1272     * that will never throw {@link ConcurrentModificationException},
1273     * and guarantees to traverse elements as they existed upon
1274     * construction of the iterator, and may (but is not guaranteed to)
1275     * reflect any modifications subsequent to construction.
1276     */
1277     public Collection<V> values() {
1278     Collection<V> vs = values;
1279     return (vs != null) ? vs : (values = new Values());
1280     }
1281    
1282     /**
1283     * Returns a {@link Set} view of the mappings contained in this map.
1284     * The set is backed by the map, so changes to the map are
1285     * reflected in the set, and vice-versa. The set supports element
1286     * removal, which removes the corresponding mapping from the map,
1287     * via the {@code Iterator.remove}, {@code Set.remove},
1288     * {@code removeAll}, {@code retainAll}, and {@code clear}
1289     * operations. It does not support the {@code add} or
1290     * {@code addAll} operations.
1291     *
1292     * <p>The view's {@code iterator} is a "weakly consistent" iterator
1293     * that will never throw {@link ConcurrentModificationException},
1294     * and guarantees to traverse elements as they existed upon
1295     * construction of the iterator, and may (but is not guaranteed to)
1296     * reflect any modifications subsequent to construction.
1297     */
1298     public Set<Map.Entry<K,V>> entrySet() {
1299     Set<Map.Entry<K,V>> es = entrySet;
1300     return (es != null) ? es : (entrySet = new EntrySet());
1301     }
1302    
1303     /**
1304     * Returns an enumeration of the keys in this table.
1305     *
1306     * @return an enumeration of the keys in this table
1307     * @see #keySet()
1308     */
1309     public Enumeration<K> keys() {
1310     return new KeyIterator();
1311     }
1312    
1313     /**
1314     * Returns an enumeration of the values in this table.
1315     *
1316     * @return an enumeration of the values in this table
1317     * @see #values()
1318     */
1319     public Enumeration<V> elements() {
1320     return new ValueIterator();
1321     }
1322    
1323     /**
1324 dl 1.2 * Returns the hash code value for this {@link Map}, i.e.,
1325     * the sum of, for each key-value pair in the map,
1326     * {@code key.hashCode() ^ value.hashCode()}.
1327     *
1328     * @return the hash code value for this map
1329 dl 1.1 */
1330     public int hashCode() {
1331     return new HashIterator().mapHashCode();
1332     }
1333    
1334     /**
1335 dl 1.2 * Returns a string representation of this map. The string
1336     * representation consists of a list of key-value mappings (in no
1337     * particular order) enclosed in braces ("{@code {}}"). Adjacent
1338     * mappings are separated by the characters {@code ", "} (comma
1339     * and space). Each key-value mapping is rendered as the key
1340     * followed by an equals sign ("{@code =}") followed by the
1341     * associated value.
1342     *
1343     * @return a string representation of this map
1344 dl 1.1 */
1345     public String toString() {
1346     return new HashIterator().mapToString();
1347     }
1348    
1349     /**
1350 dl 1.2 * Compares the specified object with this map for equality.
1351     * Returns {@code true} if the given object is a map with the same
1352     * mappings as this map. This operation may return misleading
1353     * results if either map is concurrently modified during execution
1354     * of this method.
1355     *
1356     * @param o object to be compared for equality with this map
1357     * @return {@code true} if the specified object is equal to this map
1358 dl 1.1 */
1359     public boolean equals(Object o) {
1360     if (o == this)
1361     return true;
1362     if (!(o instanceof Map))
1363     return false;
1364     Map<?,?> m = (Map<?,?>) o;
1365     try {
1366     for (Map.Entry<K,V> e : this.entrySet())
1367     if (! e.getValue().equals(m.get(e.getKey())))
1368     return false;
1369     for (Map.Entry<?,?> e : m.entrySet()) {
1370     Object k = e.getKey();
1371     Object v = e.getValue();
1372     if (k == null || v == null || !v.equals(get(k)))
1373     return false;
1374     }
1375     return true;
1376     } catch (ClassCastException unused) {
1377     return false;
1378     } catch (NullPointerException unused) {
1379     return false;
1380     }
1381     }
1382    
1383     /**
1384     * Custom Entry class used by EntryIterator.next(), that relays
1385     * setValue changes to the underlying map.
1386     */
1387     final class WriteThroughEntry extends AbstractMap.SimpleEntry<K,V> {
1388     @SuppressWarnings("unchecked")
1389     WriteThroughEntry(Object k, Object v) {
1390     super((K)k, (V)v);
1391     }
1392    
1393     /**
1394     * Sets our entry's value and writes through to the map. The
1395     * value to return is somewhat arbitrary here. Since a
1396     * WriteThroughEntry does not necessarily track asynchronous
1397     * changes, the most recent "previous" value could be
1398     * different from what we return (or could even have been
1399     * removed in which case the put will re-establish). We do not
1400     * and cannot guarantee more.
1401     */
1402     public V setValue(V value) {
1403     if (value == null) throw new NullPointerException();
1404     V v = super.setValue(value);
1405     ConcurrentHashMapV8.this.put(getKey(), value);
1406     return v;
1407     }
1408     }
1409    
1410     final class KeyIterator extends HashIterator
1411     implements Iterator<K>, Enumeration<K> {
1412     @SuppressWarnings("unchecked")
1413     public final K next() { return (K)super.nextKey(); }
1414     @SuppressWarnings("unchecked")
1415     public final K nextElement() { return (K)super.nextKey(); }
1416     }
1417    
1418     final class ValueIterator extends HashIterator
1419     implements Iterator<V>, Enumeration<V> {
1420     @SuppressWarnings("unchecked")
1421     public final V next() { return (V)super.nextValue(); }
1422     @SuppressWarnings("unchecked")
1423     public final V nextElement() { return (V)super.nextValue(); }
1424     }
1425    
1426     final class EntryIterator extends HashIterator
1427     implements Iterator<Entry<K,V>> {
1428     public final Map.Entry<K,V> next() { return super.nextEntry(); }
1429     }
1430    
1431     final class KeySet extends AbstractSet<K> {
1432     public int size() {
1433     return ConcurrentHashMapV8.this.size();
1434     }
1435     public boolean isEmpty() {
1436     return ConcurrentHashMapV8.this.isEmpty();
1437     }
1438     public void clear() {
1439     ConcurrentHashMapV8.this.clear();
1440     }
1441     public Iterator<K> iterator() {
1442     return new KeyIterator();
1443     }
1444     public boolean contains(Object o) {
1445     return ConcurrentHashMapV8.this.containsKey(o);
1446     }
1447     public boolean remove(Object o) {
1448     return ConcurrentHashMapV8.this.remove(o) != null;
1449     }
1450     }
1451    
1452     final class Values extends AbstractCollection<V> {
1453     public int size() {
1454     return ConcurrentHashMapV8.this.size();
1455     }
1456     public boolean isEmpty() {
1457     return ConcurrentHashMapV8.this.isEmpty();
1458     }
1459     public void clear() {
1460     ConcurrentHashMapV8.this.clear();
1461     }
1462     public Iterator<V> iterator() {
1463     return new ValueIterator();
1464     }
1465     public boolean contains(Object o) {
1466     return ConcurrentHashMapV8.this.containsValue(o);
1467     }
1468     }
1469    
1470     final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1471     public int size() {
1472     return ConcurrentHashMapV8.this.size();
1473     }
1474     public boolean isEmpty() {
1475     return ConcurrentHashMapV8.this.isEmpty();
1476     }
1477     public void clear() {
1478     ConcurrentHashMapV8.this.clear();
1479     }
1480     public Iterator<Map.Entry<K,V>> iterator() {
1481     return new EntryIterator();
1482     }
1483     public boolean contains(Object o) {
1484     if (!(o instanceof Map.Entry))
1485     return false;
1486     Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1487     V v = ConcurrentHashMapV8.this.get(e.getKey());
1488     return v != null && v.equals(e.getValue());
1489     }
1490     public boolean remove(Object o) {
1491     if (!(o instanceof Map.Entry))
1492     return false;
1493     Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1494     return ConcurrentHashMapV8.this.remove(e.getKey(), e.getValue());
1495     }
1496     }
1497    
1498     /* ---------------- Serialization Support -------------- */
1499    
1500     /**
1501     * Helper class used in previous version, declared for the sake of
1502     * serialization compatibility
1503     */
1504     static class Segment<K,V> extends java.util.concurrent.locks.ReentrantLock
1505     implements Serializable {
1506     private static final long serialVersionUID = 2249069246763182397L;
1507     final float loadFactor;
1508     Segment(float lf) { this.loadFactor = lf; }
1509     }
1510    
1511     /**
1512     * Saves the state of the {@code ConcurrentHashMapV8} instance to a
1513     * stream (i.e., serializes it).
1514     * @param s the stream
1515     * @serialData
1516     * the key (Object) and value (Object)
1517     * for each key-value mapping, followed by a null pair.
1518     * The key-value mappings are emitted in no particular order.
1519     */
1520     @SuppressWarnings("unchecked")
1521     private void writeObject(java.io.ObjectOutputStream s)
1522     throws java.io.IOException {
1523     if (segments == null) { // for serialization compatibility
1524     segments = (Segment<K,V>[])
1525     new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
1526     for (int i = 0; i < segments.length; ++i)
1527     segments[i] = new Segment<K,V>(loadFactor);
1528     }
1529     s.defaultWriteObject();
1530     new HashIterator().writeEntries(s);
1531     s.writeObject(null);
1532     s.writeObject(null);
1533     segments = null; // throw away
1534     }
1535    
1536     /**
1537     * Reconstitutes the instance from a
1538     * stream (i.e., deserializes it).
1539     * @param s the stream
1540     */
1541     @SuppressWarnings("unchecked")
1542     private void readObject(java.io.ObjectInputStream s)
1543     throws java.io.IOException, ClassNotFoundException {
1544     s.defaultReadObject();
1545     // find load factor in a segment, if one exists
1546     if (segments != null && segments.length != 0)
1547     this.loadFactor = segments[0].loadFactor;
1548     else
1549     this.loadFactor = DEFAULT_LOAD_FACTOR;
1550     this.initCap = DEFAULT_CAPACITY;
1551     LongAdder ct = new LongAdder(); // force final field write
1552     UNSAFE.putObjectVolatile(this, counterOffset, ct);
1553     this.segments = null; // unneeded
1554    
1555     // Read the keys and values, and put the mappings in the table
1556     for (;;) {
1557     K key = (K) s.readObject();
1558     V value = (V) s.readObject();
1559     if (key == null)
1560     break;
1561     put(key, value);
1562     }
1563     }
1564    
1565     // Unsafe mechanics
1566     private static final sun.misc.Unsafe UNSAFE;
1567     private static final long counterOffset;
1568     private static final long resizingOffset;
1569     private static final long ABASE;
1570     private static final int ASHIFT;
1571    
1572     static {
1573     int ss;
1574     try {
1575     UNSAFE = getUnsafe();
1576     Class<?> k = ConcurrentHashMapV8.class;
1577     counterOffset = UNSAFE.objectFieldOffset
1578     (k.getDeclaredField("counter"));
1579     resizingOffset = UNSAFE.objectFieldOffset
1580     (k.getDeclaredField("resizing"));
1581     Class<?> sc = Node[].class;
1582     ABASE = UNSAFE.arrayBaseOffset(sc);
1583     ss = UNSAFE.arrayIndexScale(sc);
1584     } catch (Exception e) {
1585     throw new Error(e);
1586     }
1587     if ((ss & (ss-1)) != 0)
1588     throw new Error("data type scale not a power of two");
1589     ASHIFT = 31 - Integer.numberOfLeadingZeros(ss);
1590     }
1591    
1592     /**
1593     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
1594     * Replace with a simple call to Unsafe.getUnsafe when integrating
1595     * into a jdk.
1596     *
1597     * @return a sun.misc.Unsafe
1598     */
1599     private static sun.misc.Unsafe getUnsafe() {
1600     try {
1601     return sun.misc.Unsafe.getUnsafe();
1602     } catch (SecurityException se) {
1603     try {
1604     return java.security.AccessController.doPrivileged
1605     (new java.security
1606     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
1607     public sun.misc.Unsafe run() throws Exception {
1608     java.lang.reflect.Field f = sun.misc
1609     .Unsafe.class.getDeclaredField("theUnsafe");
1610     f.setAccessible(true);
1611     return (sun.misc.Unsafe) f.get(null);
1612     }});
1613     } catch (java.security.PrivilegedActionException e) {
1614     throw new RuntimeException("Could not initialize intrinsics",
1615     e.getCause());
1616     }
1617     }
1618     }
1619    
1620     }