8134854: Bulk integration of java.util.concurrent.atomic classes
Reviewed-by: martin, psandoz, chegar
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,7 +34,6 @@
*/
package java.util.concurrent.atomic;
-import sun.misc.Unsafe;
/**
* A {@code boolean} value that may be updated atomically. See the
@@ -49,15 +48,17 @@
*/
public class AtomicBoolean implements java.io.Serializable {
private static final long serialVersionUID = 4654671469794556979L;
- // setup to use Unsafe.compareAndSwapInt for updates
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final long valueOffset;
+
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long VALUE;
static {
try {
- valueOffset = unsafe.objectFieldOffset
+ VALUE = U.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));
- } catch (Exception ex) { throw new Error(ex); }
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
private volatile int value;
@@ -96,9 +97,9 @@
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(boolean expect, boolean update) {
- int e = expect ? 1 : 0;
- int u = update ? 1 : 0;
- return unsafe.compareAndSwapInt(this, valueOffset, e, u);
+ return U.compareAndSwapInt(this, VALUE,
+ (expect ? 1 : 0),
+ (update ? 1 : 0));
}
/**
@@ -114,9 +115,9 @@
* @return {@code true} if successful
*/
public boolean weakCompareAndSet(boolean expect, boolean update) {
- int e = expect ? 1 : 0;
- int u = update ? 1 : 0;
- return unsafe.compareAndSwapInt(this, valueOffset, e, u);
+ return U.compareAndSwapInt(this, VALUE,
+ (expect ? 1 : 0),
+ (update ? 1 : 0));
}
/**
@@ -135,8 +136,7 @@
* @since 1.6
*/
public final void lazySet(boolean newValue) {
- int v = newValue ? 1 : 0;
- unsafe.putOrderedInt(this, valueOffset, v);
+ U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
}
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,9 +34,9 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.IntUnaryOperator;
+
import java.util.function.IntBinaryOperator;
-import sun.misc.Unsafe;
+import java.util.function.IntUnaryOperator;
/**
* An {@code int} value that may be updated atomically. See the
@@ -50,19 +50,20 @@
*
* @since 1.5
* @author Doug Lea
-*/
+ */
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
- // setup to use Unsafe.compareAndSwapInt for updates
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final long valueOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long VALUE;
static {
try {
- valueOffset = unsafe.objectFieldOffset
+ VALUE = U.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
- } catch (Exception ex) { throw new Error(ex); }
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
private volatile int value;
@@ -107,7 +108,7 @@
* @since 1.6
*/
public final void lazySet(int newValue) {
- unsafe.putOrderedInt(this, valueOffset, newValue);
+ U.putOrderedInt(this, VALUE, newValue);
}
/**
@@ -117,7 +118,7 @@
* @return the previous value
*/
public final int getAndSet(int newValue) {
- return unsafe.getAndSetInt(this, valueOffset, newValue);
+ return U.getAndSetInt(this, VALUE, newValue);
}
/**
@@ -130,7 +131,7 @@
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
- return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+ return U.compareAndSwapInt(this, VALUE, expect, update);
}
/**
@@ -146,7 +147,7 @@
* @return {@code true} if successful
*/
public final boolean weakCompareAndSet(int expect, int update) {
- return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+ return U.compareAndSwapInt(this, VALUE, expect, update);
}
/**
@@ -155,7 +156,7 @@
* @return the previous value
*/
public final int getAndIncrement() {
- return unsafe.getAndAddInt(this, valueOffset, 1);
+ return U.getAndAddInt(this, VALUE, 1);
}
/**
@@ -164,7 +165,7 @@
* @return the previous value
*/
public final int getAndDecrement() {
- return unsafe.getAndAddInt(this, valueOffset, -1);
+ return U.getAndAddInt(this, VALUE, -1);
}
/**
@@ -174,7 +175,7 @@
* @return the previous value
*/
public final int getAndAdd(int delta) {
- return unsafe.getAndAddInt(this, valueOffset, delta);
+ return U.getAndAddInt(this, VALUE, delta);
}
/**
@@ -183,7 +184,7 @@
* @return the updated value
*/
public final int incrementAndGet() {
- return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
+ return U.getAndAddInt(this, VALUE, 1) + 1;
}
/**
@@ -192,7 +193,7 @@
* @return the updated value
*/
public final int decrementAndGet() {
- return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
+ return U.getAndAddInt(this, VALUE, -1) - 1;
}
/**
@@ -202,7 +203,7 @@
* @return the updated value
*/
public final int addAndGet(int delta) {
- return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
+ return U.getAndAddInt(this, VALUE, delta) + delta;
}
/**
@@ -301,6 +302,7 @@
/**
* Returns the value of this {@code AtomicInteger} as an {@code int}.
+ * Equivalent to {@link #get()}.
*/
public int intValue() {
return get();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,9 +34,9 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.IntUnaryOperator;
+
import java.util.function.IntBinaryOperator;
-import sun.misc.Unsafe;
+import java.util.function.IntUnaryOperator;
/**
* An {@code int} array in which elements may be updated atomically.
@@ -49,16 +49,17 @@
public class AtomicIntegerArray implements java.io.Serializable {
private static final long serialVersionUID = 2862133569453604235L;
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final int base = unsafe.arrayBaseOffset(int[].class);
- private static final int shift;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final int ABASE;
+ private static final int ASHIFT;
private final int[] array;
static {
- int scale = unsafe.arrayIndexScale(int[].class);
+ ABASE = U.arrayBaseOffset(int[].class);
+ int scale = U.arrayIndexScale(int[].class);
if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
- shift = 31 - Integer.numberOfLeadingZeros(scale);
+ throw new Error("array index scale not a power of two");
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
}
private long checkedByteOffset(int i) {
@@ -69,7 +70,7 @@
}
private static long byteOffset(int i) {
- return ((long) i << shift) + base;
+ return ((long) i << ASHIFT) + ABASE;
}
/**
@@ -114,7 +115,7 @@
}
private int getRaw(long offset) {
- return unsafe.getIntVolatile(array, offset);
+ return U.getIntVolatile(array, offset);
}
/**
@@ -124,7 +125,7 @@
* @param newValue the new value
*/
public final void set(int i, int newValue) {
- unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
+ U.putIntVolatile(array, checkedByteOffset(i), newValue);
}
/**
@@ -135,7 +136,7 @@
* @since 1.6
*/
public final void lazySet(int i, int newValue) {
- unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
+ U.putOrderedInt(array, checkedByteOffset(i), newValue);
}
/**
@@ -147,7 +148,7 @@
* @return the previous value
*/
public final int getAndSet(int i, int newValue) {
- return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
+ return U.getAndSetInt(array, checkedByteOffset(i), newValue);
}
/**
@@ -165,7 +166,7 @@
}
private boolean compareAndSetRaw(long offset, int expect, int update) {
- return unsafe.compareAndSwapInt(array, offset, expect, update);
+ return U.compareAndSwapInt(array, offset, expect, update);
}
/**
@@ -213,7 +214,7 @@
* @return the previous value
*/
public final int getAndAdd(int i, int delta) {
- return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
+ return U.getAndAddInt(array, checkedByteOffset(i), delta);
}
/**
@@ -247,7 +248,6 @@
return getAndAdd(i, delta) + delta;
}
-
/**
* Atomically updates the element at index {@code i} with the results
* of applying the given function, returning the previous value. The
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,14 +34,14 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.IntUnaryOperator;
-import java.util.function.IntBinaryOperator;
-import sun.misc.Unsafe;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
+import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
+import java.util.function.IntBinaryOperator;
+import java.util.function.IntUnaryOperator;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
@@ -363,11 +363,11 @@
}
/**
- * Standard hotspot implementation using intrinsics
+ * Standard hotspot implementation using intrinsics.
*/
private static class AtomicIntegerFieldUpdaterImpl<T>
extends AtomicIntegerFieldUpdater<T> {
- 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<T> tclass;
private final Class<?> cclass;
@@ -391,7 +391,7 @@
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);
}
} catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException());
@@ -409,7 +409,7 @@
this.cclass = (Modifier.isProtected(modifiers) &&
caller != tclass) ? caller : null;
this.tclass = tclass;
- offset = unsafe.objectFieldOffset(field);
+ offset = U.objectFieldOffset(field);
}
/**
@@ -437,32 +437,32 @@
public boolean compareAndSet(T obj, int expect, int update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.compareAndSwapInt(obj, offset, expect, update);
+ return U.compareAndSwapInt(obj, offset, expect, update);
}
public boolean weakCompareAndSet(T obj, int expect, int update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.compareAndSwapInt(obj, offset, expect, update);
+ return U.compareAndSwapInt(obj, offset, expect, update);
}
public void set(T obj, int newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- unsafe.putIntVolatile(obj, offset, newValue);
+ U.putIntVolatile(obj, offset, newValue);
}
public void lazySet(T obj, int newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- unsafe.putOrderedInt(obj, offset, newValue);
+ U.putOrderedInt(obj, offset, newValue);
}
public final int get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.getIntVolatile(obj, offset);
+ return U.getIntVolatile(obj, offset);
}
public int getAndSet(T obj, int newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.getAndSetInt(obj, offset, newValue);
+ return U.getAndSetInt(obj, offset, newValue);
}
public int getAndIncrement(T obj) {
@@ -475,7 +475,7 @@
public int getAndAdd(T obj, int delta) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.getAndAddInt(obj, offset, delta);
+ return U.getAndAddInt(obj, offset, delta);
}
public int incrementAndGet(T obj) {
@@ -483,7 +483,7 @@
}
public int decrementAndGet(T obj) {
- return getAndAdd(obj, -1) - 1;
+ return getAndAdd(obj, -1) - 1;
}
public int addAndGet(T obj, int delta) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,9 +34,9 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.LongUnaryOperator;
+
import java.util.function.LongBinaryOperator;
-import sun.misc.Unsafe;
+import java.util.function.LongUnaryOperator;
/**
* A {@code long} value that may be updated atomically. See the
@@ -54,9 +54,8 @@
public class AtomicLong extends Number implements java.io.Serializable {
private static final long serialVersionUID = 1927816293512124184L;
- // setup to use Unsafe.compareAndSwapLong for updates
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final long valueOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long VALUE;
/**
* Records whether the underlying JVM supports lockless
@@ -74,9 +73,11 @@
static {
try {
- valueOffset = unsafe.objectFieldOffset
+ VALUE = U.objectFieldOffset
(AtomicLong.class.getDeclaredField("value"));
- } catch (Exception ex) { throw new Error(ex); }
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
private volatile long value;
@@ -111,7 +112,9 @@
* @param newValue the new value
*/
public final void set(long newValue) {
- value = newValue;
+ // Use putLongVolatile instead of ordinary volatile store when
+ // using compareAndSwapLong, for sake of some 32bit systems.
+ U.putLongVolatile(this, VALUE, newValue);
}
/**
@@ -121,7 +124,7 @@
* @since 1.6
*/
public final void lazySet(long newValue) {
- unsafe.putOrderedLong(this, valueOffset, newValue);
+ U.putOrderedLong(this, VALUE, newValue);
}
/**
@@ -131,7 +134,7 @@
* @return the previous value
*/
public final long getAndSet(long newValue) {
- return unsafe.getAndSetLong(this, valueOffset, newValue);
+ return U.getAndSetLong(this, VALUE, newValue);
}
/**
@@ -144,7 +147,7 @@
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(long expect, long update) {
- return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+ return U.compareAndSwapLong(this, VALUE, expect, update);
}
/**
@@ -160,7 +163,7 @@
* @return {@code true} if successful
*/
public final boolean weakCompareAndSet(long expect, long update) {
- return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+ return U.compareAndSwapLong(this, VALUE, expect, update);
}
/**
@@ -169,7 +172,7 @@
* @return the previous value
*/
public final long getAndIncrement() {
- return unsafe.getAndAddLong(this, valueOffset, 1L);
+ return U.getAndAddLong(this, VALUE, 1L);
}
/**
@@ -178,7 +181,7 @@
* @return the previous value
*/
public final long getAndDecrement() {
- return unsafe.getAndAddLong(this, valueOffset, -1L);
+ return U.getAndAddLong(this, VALUE, -1L);
}
/**
@@ -188,7 +191,7 @@
* @return the previous value
*/
public final long getAndAdd(long delta) {
- return unsafe.getAndAddLong(this, valueOffset, delta);
+ return U.getAndAddLong(this, VALUE, delta);
}
/**
@@ -197,7 +200,7 @@
* @return the updated value
*/
public final long incrementAndGet() {
- return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
+ return U.getAndAddLong(this, VALUE, 1L) + 1L;
}
/**
@@ -206,7 +209,7 @@
* @return the updated value
*/
public final long decrementAndGet() {
- return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
+ return U.getAndAddLong(this, VALUE, -1L) - 1L;
}
/**
@@ -216,7 +219,7 @@
* @return the updated value
*/
public final long addAndGet(long delta) {
- return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
+ return U.getAndAddLong(this, VALUE, delta) + delta;
}
/**
@@ -324,6 +327,7 @@
/**
* Returns the value of this {@code AtomicLong} as a {@code long}.
+ * Equivalent to {@link #get()}.
*/
public long longValue() {
return get();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,9 +34,9 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.LongUnaryOperator;
+
import java.util.function.LongBinaryOperator;
-import sun.misc.Unsafe;
+import java.util.function.LongUnaryOperator;
/**
* A {@code long} array in which elements may be updated atomically.
@@ -48,16 +48,17 @@
public class AtomicLongArray implements java.io.Serializable {
private static final long serialVersionUID = -2308431214976778248L;
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final int base = unsafe.arrayBaseOffset(long[].class);
- private static final int shift;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final int ABASE;
+ private static final int ASHIFT;
private final long[] array;
static {
- int scale = unsafe.arrayIndexScale(long[].class);
+ ABASE = U.arrayBaseOffset(long[].class);
+ int scale = U.arrayIndexScale(long[].class);
if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
- shift = 31 - Integer.numberOfLeadingZeros(scale);
+ throw new Error("array index scale not a power of two");
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
}
private long checkedByteOffset(int i) {
@@ -68,7 +69,7 @@
}
private static long byteOffset(int i) {
- return ((long) i << shift) + base;
+ return ((long) i << ASHIFT) + ABASE;
}
/**
@@ -113,7 +114,7 @@
}
private long getRaw(long offset) {
- return unsafe.getLongVolatile(array, offset);
+ return U.getLongVolatile(array, offset);
}
/**
@@ -123,7 +124,7 @@
* @param newValue the new value
*/
public final void set(int i, long newValue) {
- unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
+ U.putLongVolatile(array, checkedByteOffset(i), newValue);
}
/**
@@ -134,7 +135,7 @@
* @since 1.6
*/
public final void lazySet(int i, long newValue) {
- unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
+ U.putOrderedLong(array, checkedByteOffset(i), newValue);
}
/**
@@ -146,7 +147,7 @@
* @return the previous value
*/
public final long getAndSet(int i, long newValue) {
- return unsafe.getAndSetLong(array, checkedByteOffset(i), newValue);
+ return U.getAndSetLong(array, checkedByteOffset(i), newValue);
}
/**
@@ -164,7 +165,7 @@
}
private boolean compareAndSetRaw(long offset, long expect, long update) {
- return unsafe.compareAndSwapLong(array, offset, expect, update);
+ return U.compareAndSwapLong(array, offset, expect, update);
}
/**
@@ -212,7 +213,7 @@
* @return the previous value
*/
public final long getAndAdd(int i, long delta) {
- return unsafe.getAndAddLong(array, checkedByteOffset(i), delta);
+ return U.getAndAddLong(array, checkedByteOffset(i), delta);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,14 +34,14 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.LongUnaryOperator;
-import java.util.function.LongBinaryOperator;
-import sun.misc.Unsafe;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
+import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
+import java.util.function.LongBinaryOperator;
+import java.util.function.LongUnaryOperator;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
@@ -366,7 +366,7 @@
}
private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
- 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<T> tclass;
private final Class<?> cclass;
@@ -389,7 +389,7 @@
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);
}
} catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException());
@@ -407,7 +407,7 @@
this.cclass = (Modifier.isProtected(modifiers) &&
caller != tclass) ? caller : null;
this.tclass = tclass;
- offset = unsafe.objectFieldOffset(field);
+ offset = U.objectFieldOffset(field);
}
private void fullCheck(T obj) {
@@ -419,32 +419,32 @@
public boolean compareAndSet(T obj, long expect, long update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.compareAndSwapLong(obj, offset, expect, update);
+ return U.compareAndSwapLong(obj, offset, expect, update);
}
public boolean weakCompareAndSet(T obj, long expect, long update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.compareAndSwapLong(obj, offset, expect, update);
+ return U.compareAndSwapLong(obj, offset, expect, update);
}
public void set(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- unsafe.putLongVolatile(obj, offset, newValue);
+ U.putLongVolatile(obj, offset, newValue);
}
public void lazySet(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- unsafe.putOrderedLong(obj, offset, newValue);
+ U.putOrderedLong(obj, offset, newValue);
}
public long get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.getLongVolatile(obj, offset);
+ return U.getLongVolatile(obj, offset);
}
public long getAndSet(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.getAndSetLong(obj, offset, newValue);
+ return U.getAndSetLong(obj, offset, newValue);
}
public long getAndIncrement(T obj) {
@@ -457,7 +457,7 @@
public long getAndAdd(T obj, long delta) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
- return unsafe.getAndAddLong(obj, offset, delta);
+ return U.getAndAddLong(obj, offset, delta);
}
public long incrementAndGet(T obj) {
@@ -465,7 +465,7 @@
}
public long decrementAndGet(T obj) {
- return getAndAdd(obj, -1) - 1;
+ return getAndAdd(obj, -1) - 1;
}
public long addAndGet(T obj, long delta) {
@@ -490,7 +490,7 @@
private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
- 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<T> tclass;
private final Class<?> cclass;
@@ -513,7 +513,7 @@
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);
}
} catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException());
@@ -531,7 +531,7 @@
this.cclass = (Modifier.isProtected(modifiers) &&
caller != tclass) ? caller : null;
this.tclass = tclass;
- offset = unsafe.objectFieldOffset(field);
+ offset = U.objectFieldOffset(field);
}
private void fullCheck(T obj) {
@@ -544,10 +544,10 @@
public boolean compareAndSet(T obj, long expect, long update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
synchronized (this) {
- long v = unsafe.getLong(obj, offset);
+ long v = U.getLong(obj, offset);
if (v != expect)
return false;
- unsafe.putLong(obj, offset, update);
+ U.putLong(obj, offset, update);
return true;
}
}
@@ -559,7 +559,7 @@
public void set(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
synchronized (this) {
- unsafe.putLong(obj, offset, newValue);
+ U.putLong(obj, offset, newValue);
}
}
@@ -570,7 +570,7 @@
public long get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
synchronized (this) {
- return unsafe.getLong(obj, offset);
+ return U.getLong(obj, offset);
}
}
@@ -595,7 +595,7 @@
* classloader's delegation chain.
* Equivalent to the inaccessible: first.isAncestor(second).
*/
- private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+ static boolean isAncestor(ClassLoader first, ClassLoader second) {
ClassLoader acl = first;
do {
acl = acl.getParent();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java Tue Sep 29 16:44:29 2015 +0100
@@ -97,7 +97,7 @@
* Typical usage is {@code boolean[1] holder; ref = v.get(holder); }.
*
* @param markHolder an array of size of at least one. On return,
- * {@code markholder[0]} will hold the value of the mark.
+ * {@code markHolder[0]} will hold the value of the mark.
* @return the current value of the reference
*/
public V get(boolean[] markHolder) {
@@ -190,23 +190,18 @@
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
- private static final long pairOffset =
- objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class);
-
- private boolean casPair(Pair<V> cmp, Pair<V> val) {
- return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long PAIR;
+ static {
+ try {
+ PAIR = U.objectFieldOffset
+ (AtomicMarkableReference.class.getDeclaredField("pair"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
- static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
- String field, Class<?> klazz) {
- 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;
- }
+ private boolean casPair(Pair<V> cmp, Pair<V> val) {
+ return U.compareAndSwapObject(this, PAIR, cmp, val);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,9 +34,9 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.UnaryOperator;
+
import java.util.function.BinaryOperator;
-import sun.misc.Unsafe;
+import java.util.function.UnaryOperator;
/**
* An object reference that may be updated atomically. See the {@link
@@ -49,14 +49,16 @@
public class AtomicReference<V> implements java.io.Serializable {
private static final long serialVersionUID = -1848883965231344442L;
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final long valueOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long VALUE;
static {
try {
- valueOffset = unsafe.objectFieldOffset
+ VALUE = U.objectFieldOffset
(AtomicReference.class.getDeclaredField("value"));
- } catch (Exception ex) { throw new Error(ex); }
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
private volatile V value;
@@ -101,7 +103,7 @@
* @since 1.6
*/
public final void lazySet(V newValue) {
- unsafe.putOrderedObject(this, valueOffset, newValue);
+ U.putOrderedObject(this, VALUE, newValue);
}
/**
@@ -113,7 +115,7 @@
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(V expect, V update) {
- return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+ return U.compareAndSwapObject(this, VALUE, expect, update);
}
/**
@@ -129,7 +131,7 @@
* @return {@code true} if successful
*/
public final boolean weakCompareAndSet(V expect, V update) {
- return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+ return U.compareAndSwapObject(this, VALUE, expect, update);
}
/**
@@ -140,7 +142,7 @@
*/
@SuppressWarnings("unchecked")
public final V getAndSet(V newValue) {
- return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
+ return (V)U.getAndSetObject(this, VALUE, newValue);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,11 +34,11 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.UnaryOperator;
-import java.util.function.BinaryOperator;
+
+import java.lang.reflect.Array;
import java.util.Arrays;
-import java.lang.reflect.Array;
-import sun.misc.Unsafe;
+import java.util.function.BinaryOperator;
+import java.util.function.UnaryOperator;
/**
* An array of object references in which elements may be updated
@@ -52,23 +52,22 @@
public class AtomicReferenceArray<E> implements java.io.Serializable {
private static final long serialVersionUID = -6209656149925076980L;
- private static final Unsafe unsafe;
- private static final int base;
- private static final int shift;
- private static final long arrayFieldOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final int ABASE;
+ private static final int ASHIFT;
+ private static final long ARRAY;
private final Object[] array; // must have exact type Object[]
static {
try {
- unsafe = Unsafe.getUnsafe();
- arrayFieldOffset = unsafe.objectFieldOffset
+ ARRAY = U.objectFieldOffset
(AtomicReferenceArray.class.getDeclaredField("array"));
- base = unsafe.arrayBaseOffset(Object[].class);
- int scale = unsafe.arrayIndexScale(Object[].class);
+ ABASE = U.arrayBaseOffset(Object[].class);
+ int scale = U.arrayIndexScale(Object[].class);
if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
- shift = 31 - Integer.numberOfLeadingZeros(scale);
- } catch (Exception e) {
+ throw new Error("array index scale not a power of two");
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -81,7 +80,7 @@
}
private static long byteOffset(int i) {
- return ((long) i << shift) + base;
+ return ((long) i << ASHIFT) + ABASE;
}
/**
@@ -127,7 +126,7 @@
@SuppressWarnings("unchecked")
private E getRaw(long offset) {
- return (E) unsafe.getObjectVolatile(array, offset);
+ return (E) U.getObjectVolatile(array, offset);
}
/**
@@ -137,7 +136,7 @@
* @param newValue the new value
*/
public final void set(int i, E newValue) {
- unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue);
+ U.putObjectVolatile(array, checkedByteOffset(i), newValue);
}
/**
@@ -148,7 +147,7 @@
* @since 1.6
*/
public final void lazySet(int i, E newValue) {
- unsafe.putOrderedObject(array, checkedByteOffset(i), newValue);
+ U.putOrderedObject(array, checkedByteOffset(i), newValue);
}
/**
@@ -161,7 +160,7 @@
*/
@SuppressWarnings("unchecked")
public final E getAndSet(int i, E newValue) {
- return (E)unsafe.getAndSetObject(array, checkedByteOffset(i), newValue);
+ return (E)U.getAndSetObject(array, checkedByteOffset(i), newValue);
}
/**
@@ -179,7 +178,7 @@
}
private boolean compareAndSetRaw(long offset, E expect, E update) {
- return unsafe.compareAndSwapObject(array, offset, expect, update);
+ return U.compareAndSwapObject(array, offset, expect, update);
}
/**
@@ -314,17 +313,20 @@
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
+ * @param s the stream
+ * @throws ClassNotFoundException if the class of a serialized object
+ * could not be found
+ * @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException,
- java.io.InvalidObjectException {
+ throws java.io.IOException, ClassNotFoundException {
// Note: This must be changed if any additional fields are defined
Object a = s.readFields().get("array", null);
if (a == null || !a.getClass().isArray())
throw new java.io.InvalidObjectException("Not array type");
if (a.getClass() != Object[].class)
a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class);
- unsafe.putObjectVolatile(this, arrayFieldOffset, a);
+ U.putObjectVolatile(this, ARRAY, a);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,14 +34,14 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.UnaryOperator;
-import java.util.function.BinaryOperator;
-import sun.misc.Unsafe;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
+import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
+import java.util.function.BinaryOperator;
+import java.util.function.UnaryOperator;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
@@ -53,7 +53,7 @@
* independently subject to atomic updates. For example, a tree node
* might be declared as
*
- * <pre> {@code
+ * <pre> {@code
* class Node {
* private volatile Node left, right;
*
@@ -62,7 +62,7 @@
* private static AtomicReferenceFieldUpdater<Node, Node> 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 @@
private static final class AtomicReferenceFieldUpdaterImpl<T,V>
extends AtomicReferenceFieldUpdater<T,V> {
- 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<T> tclass;
private final Class<V> vclass;
@@ -323,7 +323,7 @@
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 @@
this.vclass = null;
else
this.vclass = vclass;
- offset = unsafe.objectFieldOffset(field);
+ offset = U.objectFieldOffset(field);
}
/**
@@ -386,7 +386,7 @@
(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 @@
(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 @@
(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 @@
(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 @@
(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) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java Tue Sep 29 16:44:29 2015 +0100
@@ -97,7 +97,7 @@
* 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 @@
// 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<V> cmp, Pair<V> val) {
- return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long PAIR;
+ static {
+ try {
+ PAIR = U.objectFieldOffset
+ (AtomicStampedReference.class.getDeclaredField("pair"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
- static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
- String field, Class<?> klazz) {
- 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;
- }
+ private boolean casPair(Pair<V> cmp, Pair<V> val) {
+ return U.compareAndSwapObject(this, PAIR, cmp, val);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
import java.util.function.DoubleBinaryOperator;
@@ -126,14 +127,13 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* 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 @@
* representing the state of this instance
*/
private Object writeReplace() {
- return new SerializationProxy(this);
+ return new SerializationProxy(get(), function, identity);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
/**
@@ -114,13 +115,12 @@
* @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 @@
* 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 @@
* @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 @@
* 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();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
import java.util.function.LongBinaryOperator;
@@ -124,13 +125,12 @@
* @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 @@
* 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 @@
* @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 @@
* @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 @@
* 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 @@
* representing the state of this instance
*/
private Object writeReplace() {
- return new SerializationProxy(this);
+ return new SerializationProxy(get(), function, identity);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.atomic;
+
import java.io.Serializable;
/**
@@ -116,13 +117,12 @@
* @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 @@
* 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 @@
* @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 @@
}
/**
- * 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();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Tue Sep 29 16:44:29 2015 +0100
@@ -34,9 +34,11 @@
*/
package java.util.concurrent.atomic;
-import java.util.function.LongBinaryOperator;
+
+import java.util.Arrays;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.function.DoubleBinaryOperator;
-import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.LongBinaryOperator;
/**
* A package-local class holding common representation and mechanics
@@ -121,19 +123,23 @@
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 @@
transient volatile int cellsBusy;
/**
- * Package-private default constructor
+ * Package-private default constructor.
*/
Striped64() {
}
@@ -168,14 +174,14 @@
* 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 @@
* 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java Tue Sep 29 18:01:33 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java Tue Sep 29 16:44:29 2015 +0100
@@ -40,7 +40,7 @@
* array elements to those that also provide an atomic conditional update
* operation of the form:
*
- * <pre> {@code boolean compareAndSet(expectedValue, updateValue);}</pre>
+ * <pre> {@code boolean compareAndSet(expectedValue, updateValue);}</pre>
*
* <p>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:
*
- * <pre> {@code
+ * <pre> {@code
* class Sequencer {
* private final AtomicLong sequenceNumber
* = new AtomicLong(0);
@@ -82,7 +82,7 @@
* <pre> {@code long transform(long input)}</pre>
*
* write your utility method as follows:
- * <pre> {@code
+ * <pre> {@code
* long getAndTransform(AtomicLong var) {
* long prev, next;
* do {
@@ -94,18 +94,19 @@
*
* <p>The memory effects for accesses and updates of atomics generally
* follow the rules for volatiles, as stated in
- * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
- * The Java Language Specification (17.4 Memory Model)</a>:
+ * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
+ * Chapter 17 of
+ * <cite>The Java™ Language Specification</cite></a>:
*
* <ul>
*
- * <li> {@code get} has the memory effects of reading a
+ * <li>{@code get} has the memory effects of reading a
* {@code volatile} variable.
*
- * <li> {@code set} has the memory effects of writing (assigning) a
+ * <li>{@code set} has the memory effects of writing (assigning) a
* {@code volatile} variable.
*
- * <li> {@code lazySet} has the memory effects of writing (assigning)
+ * <li>{@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}.
*
- * <li> {@code compareAndSet}
+ * <li>{@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.