71 |
|
* versions of this class, constructors may optionally specify an |
72 |
|
* expected {@code concurrencyLevel} as an additional hint for |
73 |
|
* internal sizing. Note that using many keys with exactly the same |
74 |
< |
* {@code hashCode{}} is a sure way to slow down performance of any |
74 |
> |
* {@code hashCode()} is a sure way to slow down performance of any |
75 |
|
* hash table. |
76 |
|
* |
77 |
|
* <p>This class and its views and iterators implement all of the |
351 |
|
* Encodings for special uses of Node hash fields. See above for |
352 |
|
* explanation. |
353 |
|
*/ |
354 |
< |
static final int MOVED = 0x80000000; // hash field for fowarding nodes |
354 |
> |
static final int MOVED = 0x80000000; // hash field for forwarding nodes |
355 |
|
static final int LOCKED = 0x40000000; // set/tested only as a bit |
356 |
|
static final int WAITING = 0xc0000000; // both bits set/tested together |
357 |
|
static final int HASH_BITS = 0x3fffffff; // usable bits of normal node hash |
391 |
|
/** |
392 |
|
* Key-value entry. Note that this is never exported out as a |
393 |
|
* user-visible Map.Entry (see WriteThroughEntry and SnapshotEntry |
394 |
< |
* below). Nodes with a negative hash field are special, and do |
394 |
> |
* below). Nodes with a hash field of MOVED are special, and do |
395 |
|
* not contain user keys or values. Otherwise, keys are never |
396 |
|
* null, and null val fields indicate that a node is in the |
397 |
|
* process of being deleted or created. For purposes of read-only |
595 |
|
} finally { |
596 |
|
if (!f.casHash(fh | LOCKED, fh)) { |
597 |
|
f.hash = fh; |
598 |
< |
synchronized(f) { f.notifyAll(); }; |
598 |
> |
synchronized (f) { f.notifyAll(); }; |
599 |
|
} |
600 |
|
} |
601 |
|
if (validated) { |
752 |
|
} finally { |
753 |
|
if (!f.casHash(fh | LOCKED, fh)) { |
754 |
|
f.hash = fh; |
755 |
< |
synchronized(f) { f.notifyAll(); }; |
755 |
> |
synchronized (f) { f.notifyAll(); }; |
756 |
|
} |
757 |
|
} |
758 |
|
if (validated) { |
789 |
|
setTabAt(tab, i, null); |
790 |
|
if (!node.casHash(fh, h)) { |
791 |
|
node.hash = h; |
792 |
< |
synchronized(node) { node.notifyAll(); }; |
792 |
> |
synchronized (node) { node.notifyAll(); }; |
793 |
|
} |
794 |
|
} |
795 |
|
} |
843 |
|
} finally { |
844 |
|
if (!f.casHash(fh | LOCKED, fh)) { |
845 |
|
f.hash = fh; |
846 |
< |
synchronized(f) { f.notifyAll(); }; |
846 |
> |
synchronized (f) { f.notifyAll(); }; |
847 |
|
} |
848 |
|
} |
849 |
|
if (validated) |
934 |
|
break; |
935 |
|
} |
936 |
|
} |
937 |
+ |
if (val == null) |
938 |
+ |
throw new NullPointerException(); |
939 |
|
if (added) { |
940 |
|
counter.add(1L); |
941 |
|
if (checkSize) |
942 |
|
checkForResize(); |
943 |
|
} |
942 |
– |
else if (val == null) |
943 |
– |
throw new NullPointerException(); |
944 |
|
return val; |
945 |
|
} |
946 |
|
|
1002 |
|
} finally { |
1003 |
|
if (!f.casHash(fh | LOCKED, fh)) { |
1004 |
|
f.hash = fh; |
1005 |
< |
synchronized(f) { f.notifyAll(); }; |
1005 |
> |
synchronized (f) { f.notifyAll(); }; |
1006 |
|
} |
1007 |
|
} |
1008 |
|
if (validated) { |
1099 |
|
while ((sc = sizeCtl) >= 0) { |
1100 |
|
Node[] tab = table; int n; |
1101 |
|
if (tab == null || (n = tab.length) == 0) { |
1102 |
< |
n = (sc > c)? sc : c; |
1102 |
> |
n = (sc > c) ? sc : c; |
1103 |
|
if (UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) { |
1104 |
|
try { |
1105 |
|
if (table == tab) { |
1150 |
|
continue; |
1151 |
|
} |
1152 |
|
else { // transiently use a locked forwarding node |
1153 |
< |
Node g = new Node(MOVED|LOCKED, nextTab, null, null); |
1153 |
> |
Node g = new Node(MOVED|LOCKED, nextTab, null, null); |
1154 |
|
if (!casTabAt(tab, i, f, g)) |
1155 |
|
continue; |
1156 |
|
setTabAt(nextTab, i, null); |
1271 |
|
} finally { |
1272 |
|
if (!f.casHash(fh | LOCKED, fh)) { |
1273 |
|
f.hash = fh; |
1274 |
< |
synchronized(f) { f.notifyAll(); }; |
1274 |
> |
synchronized (f) { f.notifyAll(); }; |
1275 |
|
} |
1276 |
|
} |
1277 |
|
if (validated) |
1460 |
|
if (initialCapacity < concurrencyLevel) // Use at least as many bins |
1461 |
|
initialCapacity = concurrencyLevel; // as estimated threads |
1462 |
|
long size = (long)(1.0 + (long)initialCapacity / loadFactor); |
1463 |
< |
int cap = ((size >= (long)MAXIMUM_CAPACITY) ? |
1464 |
< |
MAXIMUM_CAPACITY: tableSizeFor((int)size)); |
1463 |
> |
int cap = ((size >= (long)MAXIMUM_CAPACITY) ? |
1464 |
> |
MAXIMUM_CAPACITY: tableSizeFor((int)size)); |
1465 |
|
this.counter = new LongAdder(); |
1466 |
|
this.sizeCtl = cap; |
1467 |
|
} |
1689 |
|
* @throws IllegalStateException if the computation detectably |
1690 |
|
* attempts a recursive update to this map that would |
1691 |
|
* otherwise never complete |
1692 |
< |
* @throws RuntimeException or Error if the mappingFunction does so, |
1692 |
> |
* @throws RuntimeException or Error if the remappingFunction does so, |
1693 |
|
* in which case the mapping is unchanged |
1694 |
|
*/ |
1695 |
|
@SuppressWarnings("unchecked") |
2187 |
|
return true; |
2188 |
|
} |
2189 |
|
|
2190 |
< |
public final boolean removeAll(Collection c) { |
2190 |
> |
public final boolean removeAll(Collection<?> c) { |
2191 |
|
boolean modified = false; |
2192 |
|
for (Iterator<?> it = iter(); it.hasNext();) { |
2193 |
|
if (c.contains(it.next())) { |
2237 |
|
} |
2238 |
|
|
2239 |
|
static final class Values<K,V> extends MapView<K,V> |
2240 |
< |
implements Collection<V> { |
2240 |
> |
implements Collection<V> { |
2241 |
|
Values(ConcurrentHashMapV8<K, V> map) { super(map); } |
2242 |
|
public final boolean contains(Object o) { return map.containsValue(o); } |
2243 |
|
|
2267 |
|
} |
2268 |
|
} |
2269 |
|
|
2270 |
< |
static final class EntrySet<K,V> extends MapView<K,V> |
2270 |
> |
static final class EntrySet<K,V> extends MapView<K,V> |
2271 |
|
implements Set<Map.Entry<K,V>> { |
2272 |
|
EntrySet(ConcurrentHashMapV8<K, V> map) { super(map); } |
2273 |
|
|
2401 |
|
} |
2402 |
|
table = tab; |
2403 |
|
counter.add(size); |
2404 |
< |
sc = n - (n >>> 2) - 1; |
2404 |
> |
sc = n - (n >>> 2); |
2405 |
|
} |
2406 |
|
} finally { |
2407 |
|
sizeCtl = sc; |