10 |
|
import java.io.Serializable; |
11 |
|
import java.lang.reflect.ParameterizedType; |
12 |
|
import java.lang.reflect.Type; |
13 |
+ |
import java.util.AbstractMap; |
14 |
|
import java.util.Arrays; |
15 |
|
import java.util.Collection; |
16 |
|
import java.util.Comparator; |
132 |
|
* of supplied functions should not depend on any ordering, or on any |
133 |
|
* other objects or values that may transiently change while |
134 |
|
* computation is in progress; and except for forEach actions, should |
135 |
< |
* ideally be side-effect-free. Bulk operations on {@link Map.Entry} |
135 |
> |
* ideally be side-effect-free. Bulk operations on {@link java.util.Map.Entry} |
136 |
|
* objects do not support method {@code setValue}. |
137 |
|
* |
138 |
|
* <ul> |
236 |
|
* @param <K> the type of keys maintained by this map |
237 |
|
* @param <V> the type of mapped values |
238 |
|
*/ |
239 |
< |
public class ConcurrentHashMap<K,V> implements ConcurrentMap<K,V>, Serializable { |
239 |
> |
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable { |
240 |
|
private static final long serialVersionUID = 7249069246763182397L; |
241 |
|
|
242 |
|
/* |
263 |
|
* because they have negative hash fields and null key and value |
264 |
|
* fields. (These special nodes are either uncommon or transient, |
265 |
|
* so the impact of carrying around some unused fields is |
266 |
< |
* insignficant.) |
266 |
> |
* insignificant.) |
267 |
|
* |
268 |
|
* The table is lazily initialized to a power-of-two size upon the |
269 |
|
* first insertion. Each bin in the table normally contains a |
426 |
|
* |
427 |
|
* TreeBins also require an additional locking mechanism. While |
428 |
|
* list traversal is always possible by readers even during |
429 |
< |
* updates, tree traversal is not, mainly beause of tree-rotations |
429 |
> |
* updates, tree traversal is not, mainly because of tree-rotations |
430 |
|
* that may change the root node and/or its linkages. TreeBins |
431 |
|
* include a simple read-write lock mechanism parasitic on the |
432 |
|
* main bin-synchronization strategy: Structural adjustments |
532 |
|
/* |
533 |
|
* Encodings for Node hash fields. See above for explanation. |
534 |
|
*/ |
535 |
< |
static final int MOVED = 0x8fffffff; // (-1) hash for forwarding nodes |
536 |
< |
static final int TREEBIN = 0x80000000; // hash for heads of treea |
537 |
< |
static final int RESERVED = 0x80000001; // hash for transient reservations |
535 |
> |
static final int MOVED = -1; // hash for forwarding nodes |
536 |
> |
static final int TREEBIN = -2; // hash for roots of trees |
537 |
> |
static final int RESERVED = -3; // hash for transient reservations |
538 |
|
static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash |
539 |
|
|
540 |
|
/** Number of CPUS, to place bounds on some sizings */ |
553 |
|
* Key-value entry. This class is never exported out as a |
554 |
|
* user-mutable Map.Entry (i.e., one supporting setValue; see |
555 |
|
* MapEntry below), but can be used for read-only traversals used |
556 |
< |
* in bulk tasks. Subclasses of Node with a negativehash field |
556 |
> |
* in bulk tasks. Subclasses of Node with a negative hash field |
557 |
|
* are special, and contain null keys and values (but are never |
558 |
|
* exported). Otherwise, keys and vals are never null. |
559 |
|
*/ |
561 |
|
final int hash; |
562 |
|
final K key; |
563 |
|
volatile V val; |
564 |
< |
Node<K,V> next; |
564 |
> |
volatile Node<K,V> next; |
565 |
|
|
566 |
|
Node(int hash, K key, V val, Node<K,V> next) { |
567 |
|
this.hash = hash; |
686 |
|
* errors by users, these checks must operate on local variables, |
687 |
|
* which accounts for some odd-looking inline assignments below. |
688 |
|
* Note that calls to setTabAt always occur within locked regions, |
689 |
< |
* and so do not need full volatile semantics, but still require |
690 |
< |
* ordering to maintain concurrent readability. |
689 |
> |
* and so in principle require only release ordering, not need |
690 |
> |
* full volatile semantics, but are currently coded as volatile |
691 |
> |
* writes to be conservative. |
692 |
|
*/ |
693 |
|
|
694 |
|
@SuppressWarnings("unchecked") |
702 |
|
} |
703 |
|
|
704 |
|
static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) { |
705 |
< |
U.putOrderedObject(tab, ((long)i << ASHIFT) + ABASE, v); |
705 |
> |
U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v); |
706 |
|
} |
707 |
|
|
708 |
|
/* ---------------- Fields -------------- */ |
1323 |
|
* Saves the state of the {@code ConcurrentHashMap} instance to a |
1324 |
|
* stream (i.e., serializes it). |
1325 |
|
* @param s the stream |
1326 |
+ |
* @throws java.io.IOException if an I/O error occurs |
1327 |
|
* @serialData |
1328 |
|
* the key (Object) and value (Object) |
1329 |
|
* for each key-value mapping, followed by a null pair. |
1366 |
|
/** |
1367 |
|
* Reconstitutes the instance from a stream (that is, deserializes it). |
1368 |
|
* @param s the stream |
1369 |
+ |
* @throws ClassNotFoundException if the class of a serialized object |
1370 |
+ |
* could not be found |
1371 |
+ |
* @throws java.io.IOException if an I/O error occurs |
1372 |
|
*/ |
1373 |
|
private void readObject(java.io.ObjectInputStream s) |
1374 |
|
throws java.io.IOException, ClassNotFoundException { |
2055 |
|
* Creates a new {@link Set} backed by a ConcurrentHashMap |
2056 |
|
* from the given type to {@code Boolean.TRUE}. |
2057 |
|
* |
2058 |
+ |
* @param <K> the element type of the returned set |
2059 |
|
* @return the new set |
2060 |
|
* @since 1.8 |
2061 |
|
*/ |
2070 |
|
* |
2071 |
|
* @param initialCapacity The implementation performs internal |
2072 |
|
* sizing to accommodate this many elements. |
2073 |
+ |
* @param <K> the element type of the returned set |
2074 |
|
* @throws IllegalArgumentException if the initial capacity of |
2075 |
|
* elements is negative |
2076 |
|
* @return the new set |
2111 |
|
} |
2112 |
|
|
2113 |
|
Node<K,V> find(int h, Object k) { |
2114 |
< |
Node<K,V> e; int n; |
2115 |
< |
Node<K,V>[] tab = nextTable; |
2116 |
< |
if (k != null && tab != null && (n = tab.length) > 0 && |
2117 |
< |
(e = tabAt(tab, (n - 1) & h)) != null) { |
2118 |
< |
do { |
2114 |
> |
// loop to avoid arbitrarily deep recursion on forwarding nodes |
2115 |
> |
outer: for (Node<K,V>[] tab = nextTable;;) { |
2116 |
> |
Node<K,V> e; int n; |
2117 |
> |
if (k == null || tab == null || (n = tab.length) == 0 || |
2118 |
> |
(e = tabAt(tab, (n - 1) & h)) == null) |
2119 |
> |
return null; |
2120 |
> |
for (;;) { |
2121 |
|
int eh; K ek; |
2122 |
|
if ((eh = e.hash) == h && |
2123 |
|
((ek = e.key) == k || (ek != null && k.equals(ek)))) |
2124 |
|
return e; |
2125 |
< |
if (eh < 0) |
2126 |
< |
return e.find(h, k); |
2127 |
< |
} while ((e = e.next) != null); |
2125 |
> |
if (eh < 0) { |
2126 |
> |
if (e instanceof ForwardingNode) { |
2127 |
> |
tab = ((ForwardingNode<K,V>)e).nextTable; |
2128 |
> |
continue outer; |
2129 |
> |
} |
2130 |
> |
else |
2131 |
> |
return e.find(h, k); |
2132 |
> |
} |
2133 |
> |
if ((e = e.next) == null) |
2134 |
> |
return null; |
2135 |
> |
} |
2136 |
|
} |
2119 |
– |
return null; |
2137 |
|
} |
2138 |
|
} |
2139 |
|
|
2306 |
|
int nextn = nextTab.length; |
2307 |
|
ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab); |
2308 |
|
boolean advance = true; |
2309 |
+ |
boolean finishing = false; // to ensure sweep before committing nextTab |
2310 |
|
for (int i = 0, bound = 0;;) { |
2311 |
|
int nextIndex, nextBound, fh; Node<K,V> f; |
2312 |
|
while (advance) { |
2313 |
< |
if (--i >= bound) |
2313 |
> |
if (--i >= bound || finishing) |
2314 |
|
advance = false; |
2315 |
|
else if ((nextIndex = transferIndex) <= transferOrigin) { |
2316 |
|
i = -1; |
2326 |
|
} |
2327 |
|
} |
2328 |
|
if (i < 0 || i >= n || i + n >= nextn) { |
2329 |
+ |
if (finishing) { |
2330 |
+ |
nextTable = null; |
2331 |
+ |
table = nextTab; |
2332 |
+ |
sizeCtl = (n << 1) - (n >>> 1); |
2333 |
+ |
return; |
2334 |
+ |
} |
2335 |
|
for (int sc;;) { |
2336 |
|
if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, ++sc)) { |
2337 |
< |
if (sc == -1) { |
2338 |
< |
nextTable = null; |
2339 |
< |
table = nextTab; |
2340 |
< |
sizeCtl = (n << 1) - (n >>> 1); |
2341 |
< |
} |
2318 |
< |
return; |
2337 |
> |
if (sc != -1) |
2338 |
> |
return; |
2339 |
> |
finishing = advance = true; |
2340 |
> |
i = n; // recheck before commit |
2341 |
> |
break; |
2342 |
|
} |
2343 |
|
} |
2344 |
|
} |
2380 |
|
else |
2381 |
|
hn = new Node<K,V>(ph, pk, pv, hn); |
2382 |
|
} |
2383 |
+ |
setTabAt(nextTab, i, ln); |
2384 |
+ |
setTabAt(nextTab, i + n, hn); |
2385 |
+ |
setTabAt(tab, i, fwd); |
2386 |
+ |
advance = true; |
2387 |
|
} |
2388 |
|
else if (f instanceof TreeBin) { |
2389 |
|
TreeBin<K,V> t = (TreeBin<K,V>)f; |
2415 |
|
(hc != 0) ? new TreeBin<K,V>(lo) : t; |
2416 |
|
hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) : |
2417 |
|
(lc != 0) ? new TreeBin<K,V>(hi) : t; |
2418 |
+ |
setTabAt(nextTab, i, ln); |
2419 |
+ |
setTabAt(nextTab, i + n, hn); |
2420 |
+ |
setTabAt(tab, i, fwd); |
2421 |
+ |
advance = true; |
2422 |
|
} |
2392 |
– |
else |
2393 |
– |
ln = hn = null; |
2394 |
– |
setTabAt(nextTab, i, ln); |
2395 |
– |
setTabAt(nextTab, i + n, hn); |
2396 |
– |
setTabAt(tab, i, fwd); |
2397 |
– |
advance = true; |
2423 |
|
} |
2424 |
|
} |
2425 |
|
} |
2545 |
|
U.compareAndSwapInt(this, SIZECTL, sc, -2)) |
2546 |
|
transfer(tab, null); |
2547 |
|
} |
2548 |
< |
else if ((b = tabAt(tab, index)) != null) { |
2548 |
> |
else if ((b = tabAt(tab, index)) != null && b.hash >= 0) { |
2549 |
|
synchronized (b) { |
2550 |
|
if (tabAt(tab, index) == b) { |
2551 |
|
TreeNode<K,V> hd = null, tl = null; |
2567 |
|
} |
2568 |
|
|
2569 |
|
/** |
2570 |
< |
* Returns a list on non-TreeNodes replacing those in given list |
2570 |
> |
* Returns a list on non-TreeNodes replacing those in given list. |
2571 |
|
*/ |
2572 |
|
static <K,V> Node<K,V> untreeify(Node<K,V> b) { |
2573 |
|
Node<K,V> hd = null, tl = null; |
2705 |
|
} |
2706 |
|
|
2707 |
|
/** |
2708 |
< |
* Acquires write lock for tree restructuring |
2708 |
> |
* Acquires write lock for tree restructuring. |
2709 |
|
*/ |
2710 |
|
private final void lockRoot() { |
2711 |
|
if (!U.compareAndSwapInt(this, LOCKSTATE, 0, WRITER)) |
2713 |
|
} |
2714 |
|
|
2715 |
|
/** |
2716 |
< |
* Releases write lock for tree restructuring |
2716 |
> |
* Releases write lock for tree restructuring. |
2717 |
|
*/ |
2718 |
|
private final void unlockRoot() { |
2719 |
|
lockState = 0; |
2720 |
|
} |
2721 |
|
|
2722 |
|
/** |
2723 |
< |
* Possibly blocks awaiting root lock |
2723 |
> |
* Possibly blocks awaiting root lock. |
2724 |
|
*/ |
2725 |
|
private final void contendedLock() { |
2726 |
|
boolean waiting = false; |
2745 |
|
|
2746 |
|
/** |
2747 |
|
* Returns matching node or null if none. Tries to search |
2748 |
< |
* using tree compareisons from root, but continues linear |
2748 |
> |
* using tree comparisons from root, but continues linear |
2749 |
|
* search when lock not available. |
2750 |
|
*/ |
2751 |
|
final Node<K,V> find(int h, Object k) { |
2840 |
|
* that are accessible independently of lock. So instead we |
2841 |
|
* swap the tree linkages. |
2842 |
|
* |
2843 |
< |
* @return true if now too small so should be untreeified. |
2843 |
> |
* @return true if now too small, so should be untreeified |
2844 |
|
*/ |
2845 |
|
final boolean removeTreeNode(TreeNode<K,V> p) { |
2846 |
|
TreeNode<K,V> next = (TreeNode<K,V>)p.next; |
3235 |
|
|
3236 |
|
/** |
3237 |
|
* Base of key, value, and entry Iterators. Adds fields to |
3238 |
< |
* Traverser to support iterator.remove |
3238 |
> |
* Traverser to support iterator.remove. |
3239 |
|
*/ |
3240 |
|
static class BaseIterator<K,V> extends Traverser<K,V> { |
3241 |
|
final ConcurrentHashMap<K,V> map; |
3523 |
|
* for an element, or null if there is no transformation (in |
3524 |
|
* which case the action is not applied) |
3525 |
|
* @param action the action |
3526 |
+ |
* @param <U> the return type of the transformer |
3527 |
|
* @since 1.8 |
3528 |
|
*/ |
3529 |
|
public <U> void forEach(long parallelismThreshold, |
3547 |
|
* needed for this operation to be executed in parallel |
3548 |
|
* @param searchFunction a function returning a non-null |
3549 |
|
* result on success, else null |
3550 |
+ |
* @param <U> the return type of the search function |
3551 |
|
* @return a non-null result from applying the given search |
3552 |
|
* function on each (key, value), or null if none |
3553 |
|
* @since 1.8 |
3571 |
|
* for an element, or null if there is no transformation (in |
3572 |
|
* which case it is not combined) |
3573 |
|
* @param reducer a commutative associative combining function |
3574 |
+ |
* @param <U> the return type of the transformer |
3575 |
|
* @return the result of accumulating the given transformation |
3576 |
|
* of all (key, value) pairs |
3577 |
|
* @since 1.8 |
3601 |
|
* of all (key, value) pairs |
3602 |
|
* @since 1.8 |
3603 |
|
*/ |
3604 |
< |
public double reduceToDoubleIn(long parallelismThreshold, |
3605 |
< |
ToDoubleBiFunction<? super K, ? super V> transformer, |
3606 |
< |
double basis, |
3607 |
< |
DoubleBinaryOperator reducer) { |
3604 |
> |
public double reduceToDouble(long parallelismThreshold, |
3605 |
> |
ToDoubleBiFunction<? super K, ? super V> transformer, |
3606 |
> |
double basis, |
3607 |
> |
DoubleBinaryOperator reducer) { |
3608 |
|
if (transformer == null || reducer == null) |
3609 |
|
throw new NullPointerException(); |
3610 |
|
return new MapReduceMappingsToDoubleTask<K,V> |
3690 |
|
* for an element, or null if there is no transformation (in |
3691 |
|
* which case the action is not applied) |
3692 |
|
* @param action the action |
3693 |
+ |
* @param <U> the return type of the transformer |
3694 |
|
* @since 1.8 |
3695 |
|
*/ |
3696 |
|
public <U> void forEachKey(long parallelismThreshold, |
3714 |
|
* needed for this operation to be executed in parallel |
3715 |
|
* @param searchFunction a function returning a non-null |
3716 |
|
* result on success, else null |
3717 |
+ |
* @param <U> the return type of the search function |
3718 |
|
* @return a non-null result from applying the given search |
3719 |
|
* function on each key, or null if none |
3720 |
|
* @since 1.8 |
3757 |
|
* for an element, or null if there is no transformation (in |
3758 |
|
* which case it is not combined) |
3759 |
|
* @param reducer a commutative associative combining function |
3760 |
+ |
* @param <U> the return type of the transformer |
3761 |
|
* @return the result of accumulating the given transformation |
3762 |
|
* of all keys |
3763 |
|
* @since 1.8 |
3877 |
|
* for an element, or null if there is no transformation (in |
3878 |
|
* which case the action is not applied) |
3879 |
|
* @param action the action |
3880 |
+ |
* @param <U> the return type of the transformer |
3881 |
|
* @since 1.8 |
3882 |
|
*/ |
3883 |
|
public <U> void forEachValue(long parallelismThreshold, |
3901 |
|
* needed for this operation to be executed in parallel |
3902 |
|
* @param searchFunction a function returning a non-null |
3903 |
|
* result on success, else null |
3904 |
+ |
* @param <U> the return type of the search function |
3905 |
|
* @return a non-null result from applying the given search |
3906 |
|
* function on each value, or null if none |
3907 |
|
* @since 1.8 |
3943 |
|
* for an element, or null if there is no transformation (in |
3944 |
|
* which case it is not combined) |
3945 |
|
* @param reducer a commutative associative combining function |
3946 |
+ |
* @param <U> the return type of the transformer |
3947 |
|
* @return the result of accumulating the given transformation |
3948 |
|
* of all values |
3949 |
|
* @since 1.8 |
4061 |
|
* for an element, or null if there is no transformation (in |
4062 |
|
* which case the action is not applied) |
4063 |
|
* @param action the action |
4064 |
+ |
* @param <U> the return type of the transformer |
4065 |
|
* @since 1.8 |
4066 |
|
*/ |
4067 |
|
public <U> void forEachEntry(long parallelismThreshold, |
4085 |
|
* needed for this operation to be executed in parallel |
4086 |
|
* @param searchFunction a function returning a non-null |
4087 |
|
* result on success, else null |
4088 |
+ |
* @param <U> the return type of the search function |
4089 |
|
* @return a non-null result from applying the given search |
4090 |
|
* function on each entry, or null if none |
4091 |
|
* @since 1.8 |
4127 |
|
* for an element, or null if there is no transformation (in |
4128 |
|
* which case it is not combined) |
4129 |
|
* @param reducer a commutative associative combining function |
4130 |
+ |
* @param <U> the return type of the transformer |
4131 |
|
* @return the result of accumulating the given transformation |
4132 |
|
* of all entries |
4133 |
|
* @since 1.8 |