mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-27 18:50:07 +00:00
8134854: Bulk integration of java.util.concurrent.atomic classes
Reviewed-by: martin, psandoz, chegar
This commit is contained in:
parent
b47b3ceb6e
commit
df66629e12
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user