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.1 by jsr166, Tue Aug 9 04:05:25 2011 UTC vs.
Revision 1.12 by jsr166, Tue Oct 25 20:21:25 2011 UTC

# Line 1 | Line 1
1   /*
2 < * Written by Doug Lea with assistance from members of JCP JSR-166
3 < * Expert Group and released to the public domain, as explained at
2 > * Written by Doug Lea and Martin Buchholz with assistance from
3 > * members of JCP JSR-166 Expert Group and released to the public
4 > * domain, as explained at
5   * http://creativecommons.org/publicdomain/zero/1.0/
6   */
7  
8   package jsr166e.extra;
9 +
10   import static java.lang.Double.doubleToRawLongBits;
11   import static java.lang.Double.longBitsToDouble;
10 import sun.misc.Unsafe;
12  
13   /**
14   * A {@code double} value that may be updated atomically.  See the
15   * {@link java.util.concurrent.atomic} package specification for
16 < * description of the properties of atomic variables. An
17 < * {@code AtomicDouble} is used in applications such as atomically
18 < * incremented sequence numbers, and cannot be used as a replacement
19 < * for a {@link java.lang.Double}. However, this class does extend
20 < * {@code Number} to allow uniform access by tools and utilities that
21 < * deal with numerically-based classes.
16 > * description of the properties of atomic variables.  An {@code
17 > * AtomicDouble} is used in applications such as atomic accumulation,
18 > * and cannot be used as a replacement for a {@link Double}.  However,
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><a name="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 > * 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   *
22 * @since 1.5
37   * @author Doug Lea
38 + * @author Martin Buchholz
39   */
40   public class AtomicDouble extends Number implements java.io.Serializable {
41 <    private static final long serialVersionUID = 1927816293512124184L;
41 >    private static final long serialVersionUID = -8405198993435143622L;
42  
43 <    // setup to use Unsafe.compareAndSwapLong for updates
29 <    private static final Unsafe unsafe = Unsafe.getUnsafe();
30 <    private static final long valueOffset;
31 <
32 <    /**
33 <     * Records whether the underlying JVM supports lockless
34 <     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
35 <     * method works in either case, some constructions should be
36 <     * handled at Java level to avoid locking user-visible locks.
37 <     */
38 <    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
43 >    private transient volatile long value;
44  
45      /**
46 <     * Returns whether underlying JVM supports lockless CompareAndSet
42 <     * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
43 <     */
44 <    private static native boolean VMSupportsCS8();
45 <
46 <    static {
47 <        try {
48 <            valueOffset = unsafe.objectFieldOffset
49 <                (AtomicDouble.class.getDeclaredField("value"));
50 <        } catch (Exception ex) { throw new Error(ex); }
51 <    }
52 <
53 <    private volatile long value;
54 <
55 <    /**
56 <     * 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 62 | 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 81 | 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      /**
81       * Eventually sets to the given value.
82       *
83       * @param newValue the new value
91     * @since 1.6
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 101 | 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 (compareAndSet(currentBits, newBits))
101 <                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 126 | 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>
126 >     * <p>May <a
127 >     * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
128 >     * fail spuriously</a>
129       * and does not provide ordering guarantees, so is only rarely an
130       * appropriate alternative to {@code compareAndSet}.
131       *
132       * @param expect the expected value
133       * @param update the new value
134 <     * @return true if successful.
134 >     * @return {@code true} if successful
135       */
136      public final boolean weakCompareAndSet(double expect, double update) {
137          return compareAndSet(expect, update);
# Line 148 | Line 145 | public class AtomicDouble extends Number
145       */
146      public final double getAndAdd(double delta) {
147          while (true) {
148 <            long currentBits = value;
149 <            long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
150 <            if (compareAndSet(currentBits, nextBits))
151 <                return longBitsToDouble(currentBits);
148 >            long current = value;
149 >            double currentVal = longBitsToDouble(current);
150 >            double nextVal = currentVal + delta;
151 >            long next = doubleToRawLongBits(nextVal);
152 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
153 >                return currentVal;
154          }
155      }
156  
# Line 162 | Line 161 | public class AtomicDouble extends Number
161       * @return the updated value
162       */
163      public final double addAndGet(double delta) {
164 <        for (;;) {
165 <            double current = get();
166 <            double next = current + delta;
167 <            if (compareAndSet(current, next))
168 <                return next;
164 >        while (true) {
165 >            long current = value;
166 >            double currentVal = longBitsToDouble(current);
167 >            double nextVal = currentVal + delta;
168 >            long next = doubleToRawLongBits(nextVal);
169 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
170 >                return nextVal;
171          }
172      }
173  
174      /**
175       * Returns the String representation of the current value.
176 <     * @return the String representation of the current value.
176 >     * @return the String representation of the current value
177       */
178      public String toString() {
179          return Double.toString(get());
180      }
181  
181
182      /**
183       * Returns the value of this {@code AtomicDouble} as an {@code int}
184       * after a narrowing primitive conversion.
185       */
186      public int intValue() {
187 <        return (int)get();
187 >        return (int) get();
188      }
189  
190      /**
191 <     * Returns the value of this {@code AtomicDouble} as a {@code long}.
191 >     * Returns the value of this {@code AtomicDouble} as a {@code long}
192 >     * after a narrowing primitive conversion.
193       */
194      public long longValue() {
195 <        return (long)get();
195 >        return (long) get();
196      }
197  
198      /**
199       * Returns the value of this {@code AtomicDouble} as a {@code float}
200 <     * after a widening primitive conversion.
200 >     * after a narrowing primitive conversion.
201       */
202      public float floatValue() {
203 <        return (float)get();
203 >        return (float) get();
204      }
205  
206      /**
207 <     * Returns the value of this {@code AtomicDouble} as a {@code double}
207 <     * after a widening primitive conversion.
207 >     * Returns the value of this {@code AtomicDouble} as a {@code double}.
208       */
209      public double doubleValue() {
210          return get();
211      }
212  
213 +    /**
214 +     * Saves the state to a stream (that is, serializes it).
215 +     *
216 +     * @serialData The current value is emitted (a {@code double}).
217 +     */
218 +    private void writeObject(java.io.ObjectOutputStream s)
219 +        throws java.io.IOException{
220 +        s.defaultWriteObject();
221 +
222 +        s.writeDouble(get());
223 +    }
224 +
225 +    /**
226 +     * Reconstitutes the instance from a stream (that is, deserializes it).
227 +     */
228 +    private void readObject(java.io.ObjectInputStream s)
229 +        throws java.io.IOException, ClassNotFoundException {
230 +        s.defaultReadObject();
231 +
232 +        set(s.readDouble());
233 +    }
234 +
235 +    // Unsafe mechanics
236 +    private static final sun.misc.Unsafe unsafe = getUnsafe();
237 +    private static final long valueOffset;
238 +
239 +    static {
240 +        try {
241 +            valueOffset = unsafe.objectFieldOffset
242 +                (AtomicDouble.class.getDeclaredField("value"));
243 +        } catch (Exception ex) { throw new Error(ex); }
244 +    }
245 +
246 +    /**
247 +     * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
248 +     * Replace with a simple call to Unsafe.getUnsafe when integrating
249 +     * into a jdk.
250 +     *
251 +     * @return a sun.misc.Unsafe
252 +     */
253 +    private static sun.misc.Unsafe getUnsafe() {
254 +        try {
255 +            return sun.misc.Unsafe.getUnsafe();
256 +        } catch (SecurityException se) {
257 +            try {
258 +                return java.security.AccessController.doPrivileged
259 +                    (new java.security
260 +                     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
261 +                        public sun.misc.Unsafe run() throws Exception {
262 +                            java.lang.reflect.Field f = sun.misc
263 +                                .Unsafe.class.getDeclaredField("theUnsafe");
264 +                            f.setAccessible(true);
265 +                            return (sun.misc.Unsafe) f.get(null);
266 +                        }});
267 +            } catch (java.security.PrivilegedActionException e) {
268 +                throw new RuntimeException("Could not initialize intrinsics",
269 +                                           e.getCause());
270 +            }
271 +        }
272 +    }
273   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines