From df66629e12a4f65780940c5e8f321ec4e9777099 Mon Sep 17 00:00:00 2001 From: Doug Lea
{@code
+ * {@code
* class Node {
* private volatile Node left, right;
*
@@ -62,7 +62,7 @@ import sun.reflect.Reflection;
* private static AtomicReferenceFieldUpdater rightUpdater =
* AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
*
- * Node getLeft() { return left; }
+ * Node getLeft() { return left; }
* boolean compareAndSetLeft(Node expect, Node update) {
* return leftUpdater.compareAndSet(this, expect, update);
* }
@@ -284,7 +284,7 @@ public abstract class AtomicReferenceFieldUpdater {
private static final class AtomicReferenceFieldUpdaterImpl
extends AtomicReferenceFieldUpdater {
- private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private final long offset;
private final Class tclass;
private final Class vclass;
@@ -323,7 +323,7 @@ public abstract class AtomicReferenceFieldUpdater {
ClassLoader ccl = caller.getClassLoader();
if ((ccl != null) && (ccl != cl) &&
((cl == null) || !isAncestor(cl, ccl))) {
- sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
}
fieldClass = field.getType();
} catch (PrivilegedActionException pae) {
@@ -347,7 +347,7 @@ public abstract class AtomicReferenceFieldUpdater {
this.vclass = null;
else
this.vclass = vclass;
- offset = unsafe.objectFieldOffset(field);
+ offset = U.objectFieldOffset(field);
}
/**
@@ -386,7 +386,7 @@ public abstract class AtomicReferenceFieldUpdater {
(update != null && vclass != null &&
vclass != update.getClass()))
updateCheck(obj, update);
- return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ return U.compareAndSwapObject(obj, offset, expect, update);
}
public boolean weakCompareAndSet(T obj, V expect, V update) {
@@ -395,7 +395,7 @@ public abstract class AtomicReferenceFieldUpdater {
(update != null && vclass != null &&
vclass != update.getClass()))
updateCheck(obj, update);
- return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ return U.compareAndSwapObject(obj, offset, expect, update);
}
public void set(T obj, V newValue) {
@@ -403,7 +403,7 @@ public abstract class AtomicReferenceFieldUpdater {
(newValue != null && vclass != null &&
vclass != newValue.getClass()))
updateCheck(obj, newValue);
- unsafe.putObjectVolatile(obj, offset, newValue);
+ U.putObjectVolatile(obj, offset, newValue);
}
public void lazySet(T obj, V newValue) {
@@ -411,14 +411,14 @@ public abstract class AtomicReferenceFieldUpdater {
(newValue != null && vclass != null &&
vclass != newValue.getClass()))
updateCheck(obj, newValue);
- unsafe.putOrderedObject(obj, offset, newValue);
+ U.putOrderedObject(obj, offset, newValue);
}
@SuppressWarnings("unchecked")
public V get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null)
targetCheck(obj);
- return (V)unsafe.getObjectVolatile(obj, offset);
+ return (V)U.getObjectVolatile(obj, offset);
}
@SuppressWarnings("unchecked")
@@ -427,7 +427,7 @@ public abstract class AtomicReferenceFieldUpdater {
(newValue != null && vclass != null &&
vclass != newValue.getClass()))
updateCheck(obj, newValue);
- return (V)unsafe.getAndSetObject(obj, offset, newValue);
+ return (V)U.getAndSetObject(obj, offset, newValue);
}
private void ensureProtectedAccess(T obj) {
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java
index 56feb2febe7..40ceeb2650f 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -97,7 +97,7 @@ public class AtomicStampedReference {
* Typical usage is {@code int[1] holder; ref = v.get(holder); }.
*
* @param stampHolder an array of size of at least one. On return,
- * {@code stampholder[0]} will hold the value of the stamp.
+ * {@code stampHolder[0]} will hold the value of the stamp.
* @return the current value of the reference
*/
public V get(int[] stampHolder) {
@@ -190,23 +190,18 @@ public class AtomicStampedReference {
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
- private static final long pairOffset =
- objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);
-
- private boolean casPair(Pair cmp, Pair val) {
- return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
- }
-
- static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
- String field, Class> klazz) {
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long PAIR;
+ static {
try {
- return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
- } catch (NoSuchFieldException e) {
- // Convert Exception to corresponding Error
- NoSuchFieldError error = new NoSuchFieldError(field);
- error.initCause(e);
- throw error;
+ PAIR = U.objectFieldOffset
+ (AtomicStampedReference.class.getDeclaredField("pair"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
}
}
+
+ private boolean casPair(Pair cmp, Pair val) {
+ return U.compareAndSwapObject(this, PAIR, cmp, val);
+ }
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
index 929818d9cdb..f3e3531dbd9 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
import java.util.function.DoubleBinaryOperator;
@@ -126,14 +127,13 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* @return the current value
*/
public double get() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
double result = Double.longBitsToDouble(base);
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
+ for (Cell a : as)
+ if (a != null)
result = function.applyAsDouble
(result, Double.longBitsToDouble(a.value));
- }
}
return result;
}
@@ -147,13 +147,12 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* updating.
*/
public void reset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
base = identity;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
- a.value = identity;
- }
+ for (Cell a : as)
+ if (a != null)
+ a.reset(identity);
}
}
@@ -168,14 +167,14 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* @return the value before reset
*/
public double getThenReset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
double result = Double.longBitsToDouble(base);
base = identity;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null) {
+ for (Cell a : as) {
+ if (a != null) {
double v = Double.longBitsToDouble(a.value);
- a.value = identity;
+ a.reset(identity);
result = function.applyAsDouble(result, v);
}
}
@@ -237,21 +236,27 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* @serial
*/
private final double value;
+
/**
* The function used for updates.
* @serial
*/
private final DoubleBinaryOperator function;
+
/**
- * The identity value
+ * The identity value, represented as a long, as converted by
+ * {@link Double#doubleToRawLongBits}. The original identity
+ * can be recovered using {@link Double#longBitsToDouble}.
* @serial
*/
private final long identity;
- SerializationProxy(DoubleAccumulator a) {
- function = a.function;
- identity = a.identity;
- value = a.get();
+ SerializationProxy(double value,
+ DoubleBinaryOperator function,
+ long identity) {
+ this.value = value;
+ this.function = function;
+ this.identity = identity;
}
/**
@@ -259,7 +264,7 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* held by this proxy.
*
* @return a {@code DoubleAccumulator} object with initial state
- * held by this proxy.
+ * held by this proxy
*/
private Object readResolve() {
double d = Double.longBitsToDouble(identity);
@@ -279,7 +284,7 @@ public class DoubleAccumulator extends Striped64 implements Serializable {
* representing the state of this instance
*/
private Object writeReplace() {
- return new SerializationProxy(this);
+ return new SerializationProxy(get(), function, identity);
}
/**
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java
index f548d219ec5..57bd8c581a4 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
/**
@@ -114,13 +115,12 @@ public class DoubleAdder extends Striped64 implements Serializable {
* @return the sum
*/
public double sum() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
double sum = Double.longBitsToDouble(base);
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
+ for (Cell a : as)
+ if (a != null)
sum += Double.longBitsToDouble(a.value);
- }
}
return sum;
}
@@ -133,13 +133,12 @@ public class DoubleAdder extends Striped64 implements Serializable {
* known that no threads are concurrently updating.
*/
public void reset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
base = 0L; // relies on fact that double 0 must have same rep as long
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
- a.value = 0L;
- }
+ for (Cell a : as)
+ if (a != null)
+ a.reset();
}
}
@@ -154,14 +153,14 @@ public class DoubleAdder extends Striped64 implements Serializable {
* @return the sum
*/
public double sumThenReset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
double sum = Double.longBitsToDouble(base);
base = 0L;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null) {
+ for (Cell a : as) {
+ if (a != null) {
long v = a.value;
- a.value = 0L;
+ a.reset();
sum += Double.longBitsToDouble(v);
}
}
@@ -233,7 +232,7 @@ public class DoubleAdder extends Striped64 implements Serializable {
* held by this proxy.
*
* @return a {@code DoubleAdder} object with initial state
- * held by this proxy.
+ * held by this proxy
*/
private Object readResolve() {
DoubleAdder a = new DoubleAdder();
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
index 435aa1b90eb..0e9a8f5927b 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
import java.util.function.LongBinaryOperator;
@@ -124,13 +125,12 @@ public class LongAccumulator extends Striped64 implements Serializable {
* @return the current value
*/
public long get() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
long result = base;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
+ for (Cell a : as)
+ if (a != null)
result = function.applyAsLong(result, a.value);
- }
}
return result;
}
@@ -144,13 +144,12 @@ public class LongAccumulator extends Striped64 implements Serializable {
* updating.
*/
public void reset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
base = identity;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
- a.value = identity;
- }
+ for (Cell a : as)
+ if (a != null)
+ a.reset(identity);
}
}
@@ -165,14 +164,14 @@ public class LongAccumulator extends Striped64 implements Serializable {
* @return the value before reset
*/
public long getThenReset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
long result = base;
base = identity;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null) {
+ for (Cell a : as) {
+ if (a != null) {
long v = a.value;
- a.value = identity;
+ a.reset(identity);
result = function.applyAsLong(result, v);
}
}
@@ -234,21 +233,25 @@ public class LongAccumulator extends Striped64 implements Serializable {
* @serial
*/
private final long value;
+
/**
* The function used for updates.
* @serial
*/
private final LongBinaryOperator function;
+
/**
- * The identity value
+ * The identity value.
* @serial
*/
private final long identity;
- SerializationProxy(LongAccumulator a) {
- function = a.function;
- identity = a.identity;
- value = a.get();
+ SerializationProxy(long value,
+ LongBinaryOperator function,
+ long identity) {
+ this.value = value;
+ this.function = function;
+ this.identity = identity;
}
/**
@@ -256,7 +259,7 @@ public class LongAccumulator extends Striped64 implements Serializable {
* held by this proxy.
*
* @return a {@code LongAccumulator} object with initial state
- * held by this proxy.
+ * held by this proxy
*/
private Object readResolve() {
LongAccumulator a = new LongAccumulator(function, identity);
@@ -275,7 +278,7 @@ public class LongAccumulator extends Striped64 implements Serializable {
* representing the state of this instance
*/
private Object writeReplace() {
- return new SerializationProxy(this);
+ return new SerializationProxy(get(), function, identity);
}
/**
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java
index 6810edf0010..0248fad9c5f 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
/**
@@ -116,13 +117,12 @@ public class LongAdder extends Striped64 implements Serializable {
* @return the sum
*/
public long sum() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
long sum = base;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
+ for (Cell a : as)
+ if (a != null)
sum += a.value;
- }
}
return sum;
}
@@ -135,13 +135,12 @@ public class LongAdder extends Striped64 implements Serializable {
* known that no threads are concurrently updating.
*/
public void reset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
base = 0L;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null)
- a.value = 0L;
- }
+ for (Cell a : as)
+ if (a != null)
+ a.reset();
}
}
@@ -156,14 +155,14 @@ public class LongAdder extends Striped64 implements Serializable {
* @return the sum
*/
public long sumThenReset() {
- Cell[] as = cells; Cell a;
+ Cell[] as = cells;
long sum = base;
base = 0L;
if (as != null) {
- for (int i = 0; i < as.length; ++i) {
- if ((a = as[i]) != null) {
+ for (Cell a : as) {
+ if (a != null) {
sum += a.value;
- a.value = 0L;
+ a.reset();
}
}
}
@@ -230,11 +229,11 @@ public class LongAdder extends Striped64 implements Serializable {
}
/**
- * Return a {@code LongAdder} object with initial state
+ * Returns a {@code LongAdder} object with initial state
* held by this proxy.
*
* @return a {@code LongAdder} object with initial state
- * held by this proxy.
+ * held by this proxy
*/
private Object readResolve() {
LongAdder a = new LongAdder();
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
index a09868daba6..18d720fa391 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
@@ -34,9 +34,11 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.LongBinaryOperator;
-import java.util.function.DoubleBinaryOperator;
+
+import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.DoubleBinaryOperator;
+import java.util.function.LongBinaryOperator;
/**
* A package-local class holding common representation and mechanics
@@ -121,19 +123,23 @@ abstract class Striped64 extends Number {
volatile long value;
Cell(long x) { value = x; }
final boolean cas(long cmp, long val) {
- return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
+ return U.compareAndSwapLong(this, VALUE, cmp, val);
+ }
+ final void reset() {
+ U.putLongVolatile(this, VALUE, 0L);
+ }
+ final void reset(long identity) {
+ U.putLongVolatile(this, VALUE, identity);
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long valueOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long VALUE;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class> ak = Cell.class;
- valueOffset = UNSAFE.objectFieldOffset
- (ak.getDeclaredField("value"));
- } catch (Exception e) {
+ VALUE = U.objectFieldOffset
+ (Cell.class.getDeclaredField("value"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -159,7 +165,7 @@ abstract class Striped64 extends Number {
transient volatile int cellsBusy;
/**
- * Package-private default constructor
+ * Package-private default constructor.
*/
Striped64() {
}
@@ -168,14 +174,14 @@ abstract class Striped64 extends Number {
* CASes the base field.
*/
final boolean casBase(long cmp, long val) {
- return UNSAFE.compareAndSwapLong(this, BASE, cmp, val);
+ return U.compareAndSwapLong(this, BASE, cmp, val);
}
/**
* CASes the cellsBusy field from 0 to 1 to acquire lock.
*/
final boolean casCellsBusy() {
- return UNSAFE.compareAndSwapInt(this, CELLSBUSY, 0, 1);
+ return U.compareAndSwapInt(this, CELLSBUSY, 0, 1);
}
/**
@@ -183,7 +189,7 @@ abstract class Striped64 extends Number {
* Duplicated from ThreadLocalRandom because of packaging restrictions.
*/
static final int getProbe() {
- return UNSAFE.getInt(Thread.currentThread(), PROBE);
+ return U.getInt(Thread.currentThread(), PROBE);
}
/**
@@ -195,7 +201,7 @@ abstract class Striped64 extends Number {
probe ^= probe << 13; // xorshift
probe ^= probe >>> 17;
probe ^= probe << 5;
- UNSAFE.putInt(Thread.currentThread(), PROBE, probe);
+ U.putInt(Thread.currentThread(), PROBE, probe);
return probe;
}
@@ -220,27 +226,24 @@ abstract class Striped64 extends Number {
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
- for (;;) {
+ done: for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
if (cellsBusy == 0 && casCellsBusy()) {
- boolean created = false;
try { // Recheck under lock
Cell[] rs; int m, j;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
- created = true;
+ break done;
}
} finally {
cellsBusy = 0;
}
- if (created)
- break;
continue; // Slot is now non-empty
}
}
@@ -248,8 +251,8 @@ abstract class Striped64 extends Number {
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
- else if (a.cas(v = a.value, ((fn == null) ? v + x :
- fn.applyAsLong(v, x))))
+ else if (a.cas(v = a.value,
+ (fn == null) ? v + x : fn.applyAsLong(v, x)))
break;
else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
@@ -257,12 +260,8 @@ abstract class Striped64 extends Number {
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
- if (cells == as) { // Expand table unless stale
- Cell[] rs = new Cell[n << 1];
- for (int i = 0; i < n; ++i)
- rs[i] = as[i];
- cells = rs;
- }
+ if (cells == as) // Expand table unless stale
+ cells = Arrays.copyOf(as, n << 1);
} finally {
cellsBusy = 0;
}
@@ -272,26 +271,30 @@ abstract class Striped64 extends Number {
h = advanceProbe(h);
}
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
- boolean init = false;
try { // Initialize table
if (cells == as) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
- init = true;
+ break done;
}
} finally {
cellsBusy = 0;
}
- if (init)
- break;
}
- else if (casBase(v = base, ((fn == null) ? v + x :
- fn.applyAsLong(v, x))))
- break; // Fall back on using base
+ // Fall back on using base
+ else if (casBase(v = base,
+ (fn == null) ? v + x : fn.applyAsLong(v, x)))
+ break done;
}
}
+ private static long apply(DoubleBinaryOperator fn, long v, double x) {
+ double d = Double.longBitsToDouble(v);
+ d = (fn == null) ? d + x : fn.applyAsDouble(d, x);
+ return Double.doubleToRawLongBits(d);
+ }
+
/**
* Same as longAccumulate, but injecting long/double conversions
* in too many places to sensibly merge with long version, given
@@ -307,27 +310,24 @@ abstract class Striped64 extends Number {
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
- for (;;) {
+ done: for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(Double.doubleToRawLongBits(x));
if (cellsBusy == 0 && casCellsBusy()) {
- boolean created = false;
try { // Recheck under lock
Cell[] rs; int m, j;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
- created = true;
+ break done;
}
} finally {
cellsBusy = 0;
}
- if (created)
- break;
continue; // Slot is now non-empty
}
}
@@ -335,13 +335,7 @@ abstract class Striped64 extends Number {
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
- else if (a.cas(v = a.value,
- ((fn == null) ?
- Double.doubleToRawLongBits
- (Double.longBitsToDouble(v) + x) :
- Double.doubleToRawLongBits
- (fn.applyAsDouble
- (Double.longBitsToDouble(v), x)))))
+ else if (a.cas(v = a.value, apply(fn, v, x)))
break;
else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
@@ -349,12 +343,8 @@ abstract class Striped64 extends Number {
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
- if (cells == as) { // Expand table unless stale
- Cell[] rs = new Cell[n << 1];
- for (int i = 0; i < n; ++i)
- rs[i] = as[i];
- cells = rs;
- }
+ if (cells == as) // Expand table unless stale
+ cells = Arrays.copyOf(as, n << 1);
} finally {
cellsBusy = 0;
}
@@ -364,48 +354,38 @@ abstract class Striped64 extends Number {
h = advanceProbe(h);
}
else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
- boolean init = false;
try { // Initialize table
if (cells == as) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(Double.doubleToRawLongBits(x));
cells = rs;
- init = true;
+ break done;
}
} finally {
cellsBusy = 0;
}
- if (init)
- break;
}
- else if (casBase(v = base,
- ((fn == null) ?
- Double.doubleToRawLongBits
- (Double.longBitsToDouble(v) + x) :
- Double.doubleToRawLongBits
- (fn.applyAsDouble
- (Double.longBitsToDouble(v), x)))))
- break; // Fall back on using base
+ // Fall back on using base
+ else if (casBase(v = base, apply(fn, v, x)))
+ break done;
}
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long BASE;
private static final long CELLSBUSY;
private static final long PROBE;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class> sk = Striped64.class;
- BASE = UNSAFE.objectFieldOffset
- (sk.getDeclaredField("base"));
- CELLSBUSY = UNSAFE.objectFieldOffset
- (sk.getDeclaredField("cellsBusy"));
- Class> tk = Thread.class;
- PROBE = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomProbe"));
- } catch (Exception e) {
+ BASE = U.objectFieldOffset
+ (Striped64.class.getDeclaredField("base"));
+ CELLSBUSY = U.objectFieldOffset
+ (Striped64.class.getDeclaredField("cellsBusy"));
+
+ PROBE = U.objectFieldOffset
+ (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
index ce497eb53b9..a8e1ff34528 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
@@ -40,7 +40,7 @@
* array elements to those that also provide an atomic conditional update
* operation of the form:
*
- * {@code boolean compareAndSet(expectedValue, updateValue);}
+ * {@code boolean compareAndSet(expectedValue, updateValue);}
*
* This method (which varies in argument types across different
* classes) atomically sets a variable to the {@code updateValue} if it
@@ -67,7 +67,7 @@
* {@code AtomicInteger} provide atomic increment methods. One
* application is to generate sequence numbers, as in:
*
- *
{@code
+ * {@code
* class Sequencer {
* private final AtomicLong sequenceNumber
* = new AtomicLong(0);
@@ -82,7 +82,7 @@
* {@code long transform(long input)}
*
* write your utility method as follows:
- * {@code
+ * {@code
* long getAndTransform(AtomicLong var) {
* long prev, next;
* do {
@@ -94,18 +94,19 @@
*
* The memory effects for accesses and updates of atomics generally
* follow the rules for volatiles, as stated in
- *
- * The Java Language Specification (17.4 Memory Model):
+ *
+ * Chapter 17 of
+ * The Java™ Language Specification:
*
*
*
- * - {@code get} has the memory effects of reading a
+ *
- {@code get} has the memory effects of reading a
* {@code volatile} variable.
*
- *
- {@code set} has the memory effects of writing (assigning) a
+ *
- {@code set} has the memory effects of writing (assigning) a
* {@code volatile} variable.
*
- *
- {@code lazySet} has the memory effects of writing (assigning)
+ *
- {@code lazySet} has the memory effects of writing (assigning)
* a {@code volatile} variable except that it permits reorderings with
* subsequent (but not previous) memory actions that do not themselves
* impose reordering constraints with ordinary non-{@code volatile}
@@ -119,7 +120,7 @@
* with respect to previous or subsequent reads and writes of any
* variables other than the target of the {@code weakCompareAndSet}.
*
- *
- {@code compareAndSet}
+ *
- {@code compareAndSet}
* and all other read-and-update operations such as {@code getAndIncrement}
* have the memory effects of both reading and
* writing {@code volatile} variables.