ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
Revision: 1.1
Committed: Sun Aug 28 19:08:07 2011 UTC (12 years, 8 months ago) by dl
Branch: MAIN
Log Message:
Initial commit of CHM replacement

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