ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
(Generate patch)

Comparing jsr166/src/jsr166e/extra/AtomicDouble.java (file contents):
Revision 1.4 by jsr166, Tue Aug 9 19:10:29 2011 UTC vs.
Revision 1.19 by jsr166, Mon Jul 22 16:47:46 2013 UTC

# Line 6 | Line 6
6   */
7  
8   package jsr166e.extra;
9 +
10   import static java.lang.Double.doubleToRawLongBits;
11   import static java.lang.Double.longBitsToDouble;
12  
# Line 18 | Line 19 | import static java.lang.Double.longBitsT
19   * this class does extend {@code Number} to allow uniform access by
20   * tools and utilities that deal with numerically-based classes.
21   *
22 < * <p>This class differs from the primitive double {@code ==} operator
23 < * and from {@link Double#equals} in that it uses purely bitwise
24 < * equality in methods such as {@link #compareAndSet}, as if
25 < * implemented by:
22 > * <p id="bitEquals">This class compares primitive {@code double}
23 > * values in methods such as {@link #compareAndSet} by comparing their
24 > * bitwise representation using {@link Double#doubleToRawLongBits},
25 > * which differs from both the primitive double {@code ==} operator
26 > * and from {@link Double#equals}, as if implemented by:
27   *  <pre> {@code
28 < * boolean bitEquals(double x, double y) {
28 > * static boolean bitEquals(double x, double y) {
29   *   long xBits = Double.doubleToRawLongBits(x);
30   *   long yBits = Double.doubleToRawLongBits(y);
31   *   return xBits == yBits;
32   * }}</pre>
33   *
34 + * @see jsr166e.DoubleAdder
35 + * @see jsr166e.DoubleMaxUpdater
36 + *
37   * @author Doug Lea
38   * @author Martin Buchholz
39   */
40   public class AtomicDouble extends Number implements java.io.Serializable {
41 <    static final long serialVersionUID = -8405198993435143622L;
37 <
38 <    // setup to use Unsafe.compareAndSwapLong for updates
39 <    private static final sun.misc.Unsafe unsafe = getUnsafe();
40 <    private static final long valueOffset;
41 <
42 <    static {
43 <        try {
44 <            valueOffset = unsafe.objectFieldOffset
45 <                (AtomicDouble.class.getDeclaredField("value"));
46 <        } catch (Exception ex) { throw new Error(ex); }
47 <    }
41 >    private static final long serialVersionUID = -8405198993435143622L;
42  
43 <    private volatile long value;
43 >    private transient volatile long value;
44  
45      /**
46 <     * Creates a new AtomicDouble with the given initial value.
46 >     * Creates a new {@code AtomicDouble} with the given initial value.
47       *
48       * @param initialValue the initial value
49       */
# Line 58 | Line 52 | public class AtomicDouble extends Number
52      }
53  
54      /**
55 <     * Creates a new AtomicDouble with initial value {@code 0.0}.
55 >     * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
56       */
57 <    public AtomicDouble() { this(0.0); }
57 >    public AtomicDouble() {
58 >        // assert doubleToRawLongBits(0.0) == 0L;
59 >    }
60  
61      /**
62       * Gets the current value.
# Line 77 | Line 73 | public class AtomicDouble extends Number
73       * @param newValue the new value
74       */
75      public final void set(double newValue) {
76 <        value = doubleToRawLongBits(newValue);
76 >        long next = doubleToRawLongBits(newValue);
77 >        value = next;
78      }
79  
80      /**
# Line 86 | Line 83 | public class AtomicDouble extends Number
83       * @param newValue the new value
84       */
85      public final void lazySet(double newValue) {
86 <        unsafe.putOrderedLong(this, valueOffset, doubleToRawLongBits(newValue));
86 >        long next = doubleToRawLongBits(newValue);
87 >        unsafe.putOrderedLong(this, valueOffset, next);
88      }
89  
90      /**
# Line 96 | Line 94 | public class AtomicDouble extends Number
94       * @return the previous value
95       */
96      public final double getAndSet(double newValue) {
97 <        long newBits = doubleToRawLongBits(newValue);
97 >        long next = doubleToRawLongBits(newValue);
98          while (true) {
99 <            long currentBits = value;
100 <            if (unsafe.compareAndSwapLong(this, valueOffset,
101 <                                          currentBits, newBits))
104 <                return longBitsToDouble(currentBits);
99 >            long current = value;
100 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
101 >                return longBitsToDouble(current);
102          }
103      }
104  
105      /**
106       * Atomically sets the value to the given updated value
107 <     * if the current value {@code ==} the expected value.
107 >     * if the current value is <a href="#bitEquals">bitwise equal</a>
108 >     * to the expected value.
109       *
110       * @param expect the expected value
111       * @param update the new value
112 <     * @return true if successful. False return indicates that
113 <     * the actual value was not equal to the expected value.
112 >     * @return {@code true} if successful. False return indicates that
113 >     * the actual value was not bitwise equal to the expected value.
114       */
115      public final boolean compareAndSet(double expect, double update) {
116          return unsafe.compareAndSwapLong(this, valueOffset,
# Line 122 | Line 120 | public class AtomicDouble extends Number
120  
121      /**
122       * Atomically sets the value to the given updated value
123 <     * if the current value {@code ==} the expected value.
123 >     * if the current value is <a href="#bitEquals">bitwise equal</a>
124 >     * to the expected value.
125       *
126 <     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
127 <     * and does not provide ordering guarantees, so is only rarely an
128 <     * appropriate alternative to {@code compareAndSet}.
126 >     * <p><a
127 >     * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
128 >     * May fail spuriously and does not provide ordering guarantees</a>,
129 >     * so is only rarely an appropriate alternative to {@code compareAndSet}.
130       *
131       * @param expect the expected value
132       * @param update the new value
133 <     * @return true if successful.
133 >     * @return {@code true} if successful
134       */
135      public final boolean weakCompareAndSet(double expect, double update) {
136          return compareAndSet(expect, update);
# Line 144 | Line 144 | public class AtomicDouble extends Number
144       */
145      public final double getAndAdd(double delta) {
146          while (true) {
147 <            long currentBits = value;
148 <            long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
149 <            if (unsafe.compareAndSwapLong(this, valueOffset,
150 <                                          currentBits, nextBits))
151 <                return longBitsToDouble(currentBits);
147 >            long current = value;
148 >            double currentVal = longBitsToDouble(current);
149 >            double nextVal = currentVal + delta;
150 >            long next = doubleToRawLongBits(nextVal);
151 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
152 >                return currentVal;
153          }
154      }
155  
# Line 159 | Line 160 | public class AtomicDouble extends Number
160       * @return the updated value
161       */
162      public final double addAndGet(double delta) {
163 <        for (;;) {
164 <            double current = get();
165 <            double next = current + delta;
166 <            if (compareAndSet(current, next))
167 <                return next;
163 >        while (true) {
164 >            long current = value;
165 >            double currentVal = longBitsToDouble(current);
166 >            double nextVal = currentVal + delta;
167 >            long next = doubleToRawLongBits(nextVal);
168 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
169 >                return nextVal;
170          }
171      }
172  
173      /**
174       * Returns the String representation of the current value.
175 <     * @return the String representation of the current value.
175 >     * @return the String representation of the current value
176       */
177      public String toString() {
178          return Double.toString(get());
179      }
180  
178
181      /**
182       * Returns the value of this {@code AtomicDouble} as an {@code int}
183       * after a narrowing primitive conversion.
184       */
185      public int intValue() {
186 <        return (int)get();
186 >        return (int) get();
187      }
188  
189      /**
190 <     * Returns the value of this {@code AtomicDouble} as a {@code long}.
190 >     * Returns the value of this {@code AtomicDouble} as a {@code long}
191 >     * after a narrowing primitive conversion.
192       */
193      public long longValue() {
194 <        return (long)get();
194 >        return (long) get();
195      }
196  
197      /**
198       * Returns the value of this {@code AtomicDouble} as a {@code float}
199 <     * after a widening primitive conversion.
199 >     * after a narrowing primitive conversion.
200       */
201      public float floatValue() {
202 <        return (float)get();
202 >        return (float) get();
203      }
204  
205      /**
206 <     * Returns the value of this {@code AtomicDouble} as a {@code double}
204 <     * after a widening primitive conversion.
206 >     * Returns the value of this {@code AtomicDouble} as a {@code double}.
207       */
208      public double doubleValue() {
209          return get();
210      }
211  
212      /**
213 +     * Saves the state to a stream (that is, serializes it).
214 +     *
215 +     * @param s the stream
216 +     * @throws java.io.IOException if an I/O error occurs
217 +     * @serialData The current value is emitted (a {@code double}).
218 +     */
219 +    private void writeObject(java.io.ObjectOutputStream s)
220 +        throws java.io.IOException {
221 +        s.defaultWriteObject();
222 +
223 +        s.writeDouble(get());
224 +    }
225 +
226 +    /**
227 +     * Reconstitutes the instance from a stream (that is, deserializes it).
228 +     * @param s the stream
229 +     * @throws ClassNotFoundException if the class of a serialized object
230 +     *         could not be found
231 +     * @throws java.io.IOException if an I/O error occurs
232 +     */
233 +    private void readObject(java.io.ObjectInputStream s)
234 +        throws java.io.IOException, ClassNotFoundException {
235 +        s.defaultReadObject();
236 +
237 +        set(s.readDouble());
238 +    }
239 +
240 +    // Unsafe mechanics
241 +    private static final sun.misc.Unsafe unsafe = getUnsafe();
242 +    private static final long valueOffset;
243 +
244 +    static {
245 +        try {
246 +            valueOffset = unsafe.objectFieldOffset
247 +                (AtomicDouble.class.getDeclaredField("value"));
248 +        } catch (Exception ex) { throw new Error(ex); }
249 +    }
250 +
251 +    /**
252       * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
253       * Replace with a simple call to Unsafe.getUnsafe when integrating
254       * into a jdk.
# Line 217 | Line 258 | public class AtomicDouble extends Number
258      private static sun.misc.Unsafe getUnsafe() {
259          try {
260              return sun.misc.Unsafe.getUnsafe();
261 <        } catch (SecurityException se) {
262 <            try {
263 <                return java.security.AccessController.doPrivileged
264 <                    (new java.security
265 <                     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
266 <                        public sun.misc.Unsafe run() throws Exception {
267 <                            java.lang.reflect.Field f = sun.misc
268 <                                .Unsafe.class.getDeclaredField("theUnsafe");
269 <                            f.setAccessible(true);
270 <                            return (sun.misc.Unsafe) f.get(null);
271 <                        }});
272 <            } catch (java.security.PrivilegedActionException e) {
273 <                throw new RuntimeException("Could not initialize intrinsics",
274 <                                           e.getCause());
275 <            }
261 >        } catch (SecurityException tryReflectionInstead) {}
262 >        try {
263 >            return java.security.AccessController.doPrivileged
264 >            (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
265 >                public sun.misc.Unsafe run() throws Exception {
266 >                    Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
267 >                    for (java.lang.reflect.Field f : k.getDeclaredFields()) {
268 >                        f.setAccessible(true);
269 >                        Object x = f.get(null);
270 >                        if (k.isInstance(x))
271 >                            return k.cast(x);
272 >                    }
273 >                    throw new NoSuchFieldError("the Unsafe");
274 >                }});
275 >        } catch (java.security.PrivilegedActionException e) {
276 >            throw new RuntimeException("Could not initialize intrinsics",
277 >                                       e.getCause());
278          }
279      }
237
280   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines