8134854: Bulk integration of java.util.concurrent.atomic classes

Reviewed-by: martin, psandoz, chegar
This commit is contained in:
Doug Lea 2015-09-29 16:44:29 +01:00
parent b47b3ceb6e
commit df66629e12
18 changed files with 345 additions and 357 deletions

View File

@ -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 @@ import sun.misc.Unsafe;
*/
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 @@ public class AtomicBoolean implements java.io.Serializable {
* 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 @@ public class AtomicBoolean implements java.io.Serializable {
* @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 @@ public class AtomicBoolean implements java.io.Serializable {
* @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));
}
/**

View File

@ -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 @@ import sun.misc.Unsafe;
*
* @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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
U.putOrderedInt(this, VALUE, newValue);
}
/**
@ -117,7 +118,7 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* 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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
return U.getAndAddInt(this, VALUE, 1);
}
/**
@ -164,7 +165,7 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @return the previous value
*/
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
return U.getAndAddInt(this, VALUE, -1);
}
/**
@ -174,7 +175,7 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @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 @@ public class AtomicInteger extends Number implements java.io.Serializable {
/**
* Returns the value of this {@code AtomicInteger} as an {@code int}.
* Equivalent to {@link #get()}.
*/
public int intValue() {
return get();

View File

@ -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 @@ import sun.misc.Unsafe;
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 @@ public class AtomicIntegerArray implements java.io.Serializable {
}
private static long byteOffset(int i) {
return ((long) i << shift) + base;
return ((long) i << ASHIFT) + ABASE;
}
/**
@ -114,7 +115,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
}
private int getRaw(long offset) {
return unsafe.getIntVolatile(array, offset);
return U.getIntVolatile(array, offset);
}
/**
@ -124,7 +125,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @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 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @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 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @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 @@ public class AtomicIntegerArray implements java.io.Serializable {
}
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 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @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 @@ public class AtomicIntegerArray implements java.io.Serializable {
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

View File

@ -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.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
@ -363,11 +363,11 @@ public abstract class AtomicIntegerFieldUpdater<T> {
}
/**
* 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 @@ public abstract class AtomicIntegerFieldUpdater<T> {
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 @@ public abstract class AtomicIntegerFieldUpdater<T> {
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 abstract class AtomicIntegerFieldUpdater<T> {
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 abstract class AtomicIntegerFieldUpdater<T> {
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 abstract class AtomicIntegerFieldUpdater<T> {
}
public int decrementAndGet(T obj) {
return getAndAdd(obj, -1) - 1;
return getAndAdd(obj, -1) - 1;
}
public int addAndGet(T obj, int delta) {

View File

@ -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 @@ import sun.misc.Unsafe;
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 @@ public class AtomicLong extends Number implements java.io.Serializable {
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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(long newValue) {
unsafe.putOrderedLong(this, valueOffset, newValue);
U.putOrderedLong(this, VALUE, newValue);
}
/**
@ -131,7 +134,7 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* 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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @return the previous value
*/
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, valueOffset, 1L);
return U.getAndAddLong(this, VALUE, 1L);
}
/**
@ -178,7 +181,7 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @return the previous value
*/
public final long getAndDecrement() {
return unsafe.getAndAddLong(this, valueOffset, -1L);
return U.getAndAddLong(this, VALUE, -1L);
}
/**
@ -188,7 +191,7 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @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 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @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 @@ public class AtomicLong extends Number implements java.io.Serializable {
/**
* Returns the value of this {@code AtomicLong} as a {@code long}.
* Equivalent to {@link #get()}.
*/
public long longValue() {
return get();

View File

@ -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 @@ import sun.misc.Unsafe;
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 @@ public class AtomicLongArray implements java.io.Serializable {
}
private static long byteOffset(int i) {
return ((long) i << shift) + base;
return ((long) i << ASHIFT) + ABASE;
}
/**
@ -113,7 +114,7 @@ public class AtomicLongArray implements java.io.Serializable {
}
private long getRaw(long offset) {
return unsafe.getLongVolatile(array, offset);
return U.getLongVolatile(array, offset);
}
/**
@ -123,7 +124,7 @@ public class AtomicLongArray implements java.io.Serializable {
* @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 @@ public class AtomicLongArray implements java.io.Serializable {
* @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 @@ public class AtomicLongArray implements java.io.Serializable {
* @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 @@ public class AtomicLongArray implements java.io.Serializable {
}
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 @@ public class AtomicLongArray implements java.io.Serializable {
* @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);
}
/**

View File

@ -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.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.LongBinaryOperator;
import java.util.function.LongUnaryOperator;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
@ -366,7 +366,7 @@ public abstract class AtomicLongFieldUpdater<T> {
}
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 @@ public abstract class AtomicLongFieldUpdater<T> {
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 @@ public abstract class AtomicLongFieldUpdater<T> {
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 abstract class AtomicLongFieldUpdater<T> {
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 abstract class AtomicLongFieldUpdater<T> {
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 abstract class AtomicLongFieldUpdater<T> {
}
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 @@ public abstract class AtomicLongFieldUpdater<T> {
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 @@ public abstract class AtomicLongFieldUpdater<T> {
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 @@ public abstract class AtomicLongFieldUpdater<T> {
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 abstract class AtomicLongFieldUpdater<T> {
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 abstract class AtomicLongFieldUpdater<T> {
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 abstract class AtomicLongFieldUpdater<T> {
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 @@ public abstract class AtomicLongFieldUpdater<T> {
* 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();

View File

@ -97,7 +97,7 @@ public class AtomicMarkableReference<V> {
* 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 @@ public class AtomicMarkableReference<V> {
// 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);
}
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
(AtomicMarkableReference.class.getDeclaredField("pair"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
private boolean casPair(Pair<V> cmp, Pair<V> val) {
return U.compareAndSwapObject(this, PAIR, cmp, val);
}
}

View File

@ -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 @@ import sun.misc.Unsafe;
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 @@ public class AtomicReference<V> implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(V newValue) {
unsafe.putOrderedObject(this, valueOffset, newValue);
U.putOrderedObject(this, VALUE, newValue);
}
/**
@ -113,7 +115,7 @@ public class AtomicReference<V> implements java.io.Serializable {
* 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 @@ public class AtomicReference<V> implements java.io.Serializable {
* @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 @@ public class AtomicReference<V> implements java.io.Serializable {
*/
@SuppressWarnings("unchecked")
public final V getAndSet(V newValue) {
return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
return (V)U.getAndSetObject(this, VALUE, newValue);
}
/**

View File

@ -34,11 +34,11 @@
*/
package java.util.concurrent.atomic;
import java.util.function.UnaryOperator;
import java.util.function.BinaryOperator;
import java.util.Arrays;
import java.lang.reflect.Array;
import sun.misc.Unsafe;
import java.util.Arrays;
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 @@ import sun.misc.Unsafe;
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 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
}
private static long byteOffset(int i) {
return ((long) i << shift) + base;
return ((long) i << ASHIFT) + ABASE;
}
/**
@ -127,7 +126,7 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
@SuppressWarnings("unchecked")
private E getRaw(long offset) {
return (E) unsafe.getObjectVolatile(array, offset);
return (E) U.getObjectVolatile(array, offset);
}
/**
@ -137,7 +136,7 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* @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 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* @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 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
*/
@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 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
}
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 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
/**
* 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);
}
}

View File

@ -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.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
@ -53,7 +53,7 @@ import sun.reflect.Reflection;
* 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 @@ import sun.reflect.Reflection;
* 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 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
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 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
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<T,V> {
this.vclass = null;
else
this.vclass = vclass;
offset = unsafe.objectFieldOffset(field);
offset = U.objectFieldOffset(field);
}
/**
@ -386,7 +386,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
(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<T,V> {
(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<T,V> {
(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<T,V> {
(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<T,V> {
(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) {

View File

@ -97,7 +97,7 @@ public class AtomicStampedReference<V> {
* 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<V> {
// 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);
}
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<V> cmp, Pair<V> val) {
return U.compareAndSwapObject(this, PAIR, cmp, val);
}
}

View File

@ -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);
}
/**

View File

@ -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();

View File

@ -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);
}
/**

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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&trade; 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.