ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
Revision: 1.5
Committed: Tue Aug 30 11:35:39 2011 UTC (12 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.4: +34 -16 lines
Log Message:
Documentation improvements; trap computeIfAbsent misuse

File Contents

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