--- jsr166/src/jsr166e/extra/AtomicDouble.java 2011/10/20 03:08:02 1.8 +++ jsr166/src/jsr166e/extra/AtomicDouble.java 2013/07/22 16:47:46 1.19 @@ -19,13 +19,13 @@ import static java.lang.Double.longBitsT * this class does extend {@code Number} to allow uniform access by * tools and utilities that deal with numerically-based classes. * - *

This class compares primitive {@code double} + *

This class compares primitive {@code double} * values in methods such as {@link #compareAndSet} by comparing their * bitwise representation using {@link Double#doubleToRawLongBits}, * 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;
@@ -40,7 +40,7 @@ import static java.lang.Double.longBitsT
 public class AtomicDouble extends Number implements java.io.Serializable {
     private static final long serialVersionUID = -8405198993435143622L;
 
-    private volatile long value;
+    private transient volatile long value;
 
     /**
      * Creates a new {@code AtomicDouble} with the given initial value.
@@ -54,7 +54,9 @@ public class AtomicDouble extends Number
     /**
      * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
      */
-    public AtomicDouble() { this(0.0); }
+    public AtomicDouble() {
+        // assert doubleToRawLongBits(0.0) == 0L;
+    }
 
     /**
      * Gets the current value.
@@ -121,9 +123,10 @@ public class AtomicDouble extends Number
      * if the current value is bitwise equal
      * to the expected value.
      *
-     * 

May fail spuriously - * and does not provide ordering guarantees, so is only rarely an - * appropriate alternative to {@code compareAndSet}. + *

+ * May fail spuriously and does not provide ordering guarantees, + * so is only rarely an appropriate alternative to {@code compareAndSet}. * * @param expect the expected value * @param update the new value @@ -180,7 +183,7 @@ public class AtomicDouble extends Number * after a narrowing primitive conversion. */ public int intValue() { - return (int)get(); + return (int) get(); } /** @@ -188,7 +191,7 @@ public class AtomicDouble extends Number * after a narrowing primitive conversion. */ public long longValue() { - return (long)get(); + return (long) get(); } /** @@ -196,7 +199,7 @@ public class AtomicDouble extends Number * after a narrowing primitive conversion. */ public float floatValue() { - return (float)get(); + return (float) get(); } /** @@ -206,6 +209,34 @@ public class AtomicDouble extends Number return get(); } + /** + * Saves the state to a stream (that is, serializes it). + * + * @param s the stream + * @throws java.io.IOException if an I/O error occurs + * @serialData The current value is emitted (a {@code double}). + */ + private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException { + s.defaultWriteObject(); + + s.writeDouble(get()); + } + + /** + * 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 { + s.defaultReadObject(); + + set(s.readDouble()); + } + // Unsafe mechanics private static final sun.misc.Unsafe unsafe = getUnsafe(); private static final long valueOffset; @@ -227,21 +258,23 @@ public class AtomicDouble extends Number 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() { - public sun.misc.Unsafe run() throws Exception { - java.lang.reflect.Field f = sun.misc - .Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - return (sun.misc.Unsafe) f.get(null); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } + } catch (SecurityException tryReflectionInstead) {} + try { + return java.security.AccessController.doPrivileged + (new java.security.PrivilegedExceptionAction() { + public sun.misc.Unsafe run() throws Exception { + Class k = sun.misc.Unsafe.class; + for (java.lang.reflect.Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (k.isInstance(x)) + return k.cast(x); + } + throw new NoSuchFieldError("the Unsafe"); + }}); + } catch (java.security.PrivilegedActionException e) { + throw new RuntimeException("Could not initialize intrinsics", + e.getCause()); } } }