479 |
|
Cell(long x) { value = x; } |
480 |
|
} |
481 |
|
|
482 |
– |
/** |
483 |
– |
* Holder for the thread-local hash code determining which |
484 |
– |
* Cell to use. The code is initialized via the |
485 |
– |
* cellHashCodeGenerator, but may be moved upon collisions. |
486 |
– |
*/ |
487 |
– |
static final class CellHashCode { |
488 |
– |
int code; |
489 |
– |
} |
490 |
– |
|
491 |
– |
/** |
492 |
– |
* Generates initial value for per-thread CellHashCodes |
493 |
– |
*/ |
494 |
– |
static final AtomicInteger cellHashCodeGenerator = new AtomicInteger(); |
495 |
– |
|
496 |
– |
/** |
497 |
– |
* Increment for cellHashCodeGenerator. See class ThreadLocal |
498 |
– |
* for explanation. |
499 |
– |
*/ |
500 |
– |
static final int SEED_INCREMENT = 0x61c88647; |
501 |
– |
|
502 |
– |
/** |
503 |
– |
* Per-thread counter hash codes. Shared across all instances. |
504 |
– |
*/ |
505 |
– |
static final ThreadLocal<CellHashCode> threadCellHashCode = |
506 |
– |
new ThreadLocal<CellHashCode>(); |
507 |
– |
|
482 |
|
/* ---------------- Fields -------------- */ |
483 |
|
|
484 |
|
/** |
1817 |
|
Cell[] as; long b, s; |
1818 |
|
if ((as = counterCells) != null || |
1819 |
|
!U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) { |
1820 |
< |
CellHashCode hc; Cell a; long v; int m; |
1820 |
> |
Cell a; long v; int m; |
1821 |
|
boolean uncontended = true; |
1822 |
< |
if ((hc = threadCellHashCode.get()) == null || |
1823 |
< |
as == null || (m = as.length - 1) < 0 || |
1850 |
< |
(a = as[m & hc.code]) == null || |
1822 |
> |
if (as == null || (m = as.length - 1) < 0 || |
1823 |
> |
(a = as[ThreadLocalRandom.getProbe() & m]) == null || |
1824 |
|
!(uncontended = |
1825 |
|
U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) { |
1826 |
< |
fullAddCount(x, hc, uncontended); |
1826 |
> |
fullAddCount(x, uncontended); |
1827 |
|
return; |
1828 |
|
} |
1829 |
|
if (check <= 1) |
2046 |
|
} |
2047 |
|
|
2048 |
|
// See LongAdder version for explanation |
2049 |
< |
private final void fullAddCount(long x, CellHashCode hc, |
2077 |
< |
boolean wasUncontended) { |
2049 |
> |
private final void fullAddCount(long x, boolean wasUncontended) { |
2050 |
|
int h; |
2051 |
< |
if (hc == null) { |
2052 |
< |
hc = new CellHashCode(); |
2053 |
< |
int s = cellHashCodeGenerator.addAndGet(SEED_INCREMENT); |
2054 |
< |
h = hc.code = (s == 0) ? 1 : s; // Avoid zero |
2083 |
< |
threadCellHashCode.set(hc); |
2051 |
> |
if ((h = ThreadLocalRandom.getProbe()) == 0) { |
2052 |
> |
ThreadLocalRandom.localInit(); // force initialization |
2053 |
> |
h = ThreadLocalRandom.getProbe(); |
2054 |
> |
wasUncontended = true; |
2055 |
|
} |
2085 |
– |
else |
2086 |
– |
h = hc.code; |
2056 |
|
boolean collide = false; // True if last slot nonempty |
2057 |
|
for (;;) { |
2058 |
|
Cell[] as; Cell a; int n; long v; |
2104 |
|
collide = false; |
2105 |
|
continue; // Retry with expanded table |
2106 |
|
} |
2107 |
< |
h ^= h << 13; // Rehash |
2139 |
< |
h ^= h >>> 17; |
2140 |
< |
h ^= h << 5; |
2107 |
> |
h = ThreadLocalRandom.advanceProbe(h); |
2108 |
|
} |
2109 |
|
else if (cellsBusy == 0 && counterCells == as && |
2110 |
|
U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { |
2125 |
|
else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x)) |
2126 |
|
break; // Fall back on using base |
2127 |
|
} |
2161 |
– |
hc.code = h; // Record index for next time |
2128 |
|
} |
2129 |
|
|
2130 |
|
/* ----------------Table Traversal -------------- */ |
2325 |
|
|
2326 |
|
// spliterator support |
2327 |
|
|
2328 |
< |
public long exactSizeIfKnown() { |
2329 |
< |
return -1; |
2328 |
> |
public boolean hasExactSize() { |
2329 |
> |
return false; |
2330 |
|
} |
2331 |
|
|
2332 |
|
public boolean hasExactSplits() { |
2947 |
|
|
2948 |
|
public final K nextElement() { return next(); } |
2949 |
|
|
2950 |
< |
public Iterator<K> iterator() { return this; } |
2950 |
> |
public Iterator<K> asIterator() { return this; } |
2951 |
|
|
2952 |
|
public void forEach(Block<? super K> action) { |
2953 |
|
if (action == null) throw new NullPointerException(); |
2954 |
|
while (advance() != null) |
2955 |
|
action.accept((K)nextKey); |
2956 |
|
} |
2957 |
+ |
|
2958 |
+ |
public boolean tryAdvance(Block<? super K> block) { |
2959 |
+ |
if (block == null) throw new NullPointerException(); |
2960 |
+ |
if (advance() == null) |
2961 |
+ |
return false; |
2962 |
+ |
block.accept((K)nextKey); |
2963 |
+ |
return true; |
2964 |
+ |
} |
2965 |
|
} |
2966 |
|
|
2967 |
|
@SuppressWarnings("serial") static final class ValueIterator<K,V> |
2987 |
|
|
2988 |
|
public final V nextElement() { return next(); } |
2989 |
|
|
2990 |
< |
public Iterator<V> iterator() { return this; } |
2990 |
> |
public Iterator<V> asIterator() { return this; } |
2991 |
|
|
2992 |
|
public void forEach(Block<? super V> action) { |
2993 |
|
if (action == null) throw new NullPointerException(); |
2995 |
|
while ((v = advance()) != null) |
2996 |
|
action.accept(v); |
2997 |
|
} |
2998 |
+ |
|
2999 |
+ |
public boolean tryAdvance(Block<? super V> block) { |
3000 |
+ |
V v; |
3001 |
+ |
if (block == null) throw new NullPointerException(); |
3002 |
+ |
if ((v = advance()) == null) |
3003 |
+ |
return false; |
3004 |
+ |
block.accept(v); |
3005 |
+ |
return true; |
3006 |
+ |
} |
3007 |
+ |
|
3008 |
|
} |
3009 |
|
|
3010 |
|
@SuppressWarnings("serial") static final class EntryIterator<K,V> |
3029 |
|
return new MapEntry<K,V>((K)k, v, map); |
3030 |
|
} |
3031 |
|
|
3032 |
< |
public Iterator<Map.Entry<K,V>> iterator() { return this; } |
3032 |
> |
public Iterator<Map.Entry<K,V>> asIterator() { return this; } |
3033 |
|
|
3034 |
|
public void forEach(Block<? super Map.Entry<K,V>> action) { |
3035 |
|
if (action == null) throw new NullPointerException(); |
3037 |
|
while ((v = advance()) != null) |
3038 |
|
action.accept(entryFor((K)nextKey, v)); |
3039 |
|
} |
3040 |
+ |
|
3041 |
+ |
public boolean tryAdvance(Block<? super Map.Entry<K,V>> block) { |
3042 |
+ |
V v; |
3043 |
+ |
if (block == null) throw new NullPointerException(); |
3044 |
+ |
if ((v = advance()) == null) |
3045 |
+ |
return false; |
3046 |
+ |
block.accept(entryFor((K)nextKey, v)); |
3047 |
+ |
return true; |
3048 |
+ |
} |
3049 |
+ |
|
3050 |
|
} |
3051 |
|
|
3052 |
|
/** |