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

File Contents

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