--- jsr166/src/jsr166e/extra/AtomicDoubleArray.java 2011/08/10 02:03:29 1.1 +++ jsr166/src/jsr166e/extra/AtomicDoubleArray.java 2013/02/11 06:29:57 1.7 @@ -20,11 +20,11 @@ import static java.lang.Double.longBitsT * which differs from both the primitive double {@code ==} operator * and from {@link Double#equals}, as if implemented by: *
{@code - * boolean bitEquals(double x, double y) { + * static boolean bitEquals(double x, double y) { * long xBits = Double.doubleToRawLongBits(x); * long yBits = Double.doubleToRawLongBits(y); * return xBits == yBits; - * }}+ * }} * * @author Doug Lea * @author Martin Buchholz @@ -32,7 +32,7 @@ import static java.lang.Double.longBitsT public class AtomicDoubleArray implements java.io.Serializable { private static final long serialVersionUID = -2308431214976778248L; - private final long[] array; + private final transient long[] array; private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) @@ -162,7 +162,9 @@ public class AtomicDoubleArray implement * if the current value is bitwise equal * to the expected value. * - *
May fail spuriously + *
May
+ * fail spuriously
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
*
@@ -222,9 +224,10 @@ public class AtomicDoubleArray implement
if (iMax == -1)
return "[]";
- StringBuilder b = new StringBuilder();
+ // Double.toString(Math.PI).length() == 17
+ StringBuilder b = new StringBuilder((17 + 2) * (iMax + 1));
b.append('[');
- for (int i = 0; ; i++) {
+ for (int i = 0;; i++) {
b.append(longBitsToDouble(getRaw(byteOffset(i))));
if (i == iMax)
return b.append(']').toString();
@@ -232,16 +235,59 @@ public class AtomicDoubleArray implement
}
}
+ /**
+ * Saves the state to a stream (that is, serializes it).
+ *
+ * @serialData The length of the array is emitted (int), followed by all
+ * of its elements (each a {@code double}) in the proper order.
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ s.defaultWriteObject();
+
+ // Write out array length
+ int length = length();
+ s.writeInt(length);
+
+ // Write out all elements in the proper order.
+ for (int i = 0; i < length; i++)
+ s.writeDouble(get(i));
+ }
+
+ /**
+ * Reconstitutes the instance from a stream (that is, deserializes it).
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ // Read in array length and allocate array
+ int length = s.readInt();
+ unsafe.putObjectVolatile(this, arrayOffset, new long[length]);
+
+ // Read in all elements in the proper order.
+ for (int i = 0; i < length; i++)
+ set(i, s.readDouble());
+ }
+
// Unsafe mechanics
private static final sun.misc.Unsafe unsafe = getUnsafe();
+ private static final long arrayOffset;
private static final int base = unsafe.arrayBaseOffset(long[].class);
private static final int shift;
static {
- int scale = unsafe.arrayIndexScale(long[].class);
- if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
- shift = 31 - Integer.numberOfLeadingZeros(scale);
+ try {
+ Class> k = AtomicDoubleArray.class;
+ arrayOffset = unsafe.objectFieldOffset
+ (k.getDeclaredField("array"));
+ int scale = unsafe.arrayIndexScale(long[].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(e);
+ }
}
/**
@@ -254,21 +300,23 @@ public class AtomicDoubleArray implement
private static sun.misc.Unsafe getUnsafe() {
try {
return sun.misc.Unsafe.getUnsafe();
- } catch (SecurityException se) {
- try {
- return java.security.AccessController.doPrivileged
- (new java.security
- .PrivilegedExceptionAction