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.3 by jsr166, Tue Aug 9 08:28:54 2011 UTC vs.
Revision 1.8 by jsr166, Thu Oct 20 03:08:02 2011 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><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   * boolean bitEquals(double x, double y) {
29   *   long xBits = Double.doubleToRawLongBits(x);
# Line 29 | Line 31 | import static java.lang.Double.longBitsT
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 <    /**
43 <     * Records whether the underlying JVM supports lockless
44 <     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
45 <     * method works in either case, some constructions should be
46 <     * handled at Java level to avoid locking user-visible locks.
47 <     */
48 <    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
49 <
50 <    /**
51 <     * Returns whether underlying JVM supports lockless CompareAndSet
52 <     * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
53 <     */
54 <    private static boolean VMSupportsCS8() {
55 <        final Class<?> klazz = java.util.concurrent.atomic.AtomicLong.class;
56 <        return java.security.AccessController.doPrivileged
57 <            (new java.security.PrivilegedAction<Boolean>() {
58 <                public Boolean run() {
59 <                    try {
60 <                        java.lang.reflect.Method m =
61 <                            klazz.getDeclaredMethod("VMSupportsCS8", new Class<?>[0]);
62 <                        m.setAccessible(true);
63 <                        return (Boolean) m.invoke(new Class<?>[0]);
64 <                    } catch (Throwable t) { throw new Error(t); }
65 <                }});
66 <    }
67 <
68 <    static {
69 <        try {
70 <            valueOffset = unsafe.objectFieldOffset
71 <                (AtomicDouble.class.getDeclaredField("value"));
72 <        } catch (Exception ex) { throw new Error(ex); }
73 <    }
41 >    private static final long serialVersionUID = -8405198993435143622L;
42  
43      private 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 84 | 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); }
58  
# Line 103 | Line 71 | public class AtomicDouble extends Number
71       * @param newValue the new value
72       */
73      public final void set(double newValue) {
74 <        value = doubleToRawLongBits(newValue);
74 >        long next = doubleToRawLongBits(newValue);
75 >        value = next;
76      }
77  
78      /**
# Line 112 | Line 81 | public class AtomicDouble extends Number
81       * @param newValue the new value
82       */
83      public final void lazySet(double newValue) {
84 <        unsafe.putOrderedLong(this, valueOffset, doubleToRawLongBits(newValue));
84 >        long next = doubleToRawLongBits(newValue);
85 >        unsafe.putOrderedLong(this, valueOffset, next);
86      }
87  
88      /**
# Line 122 | Line 92 | public class AtomicDouble extends Number
92       * @return the previous value
93       */
94      public final double getAndSet(double newValue) {
95 <        long newBits = doubleToRawLongBits(newValue);
95 >        long next = doubleToRawLongBits(newValue);
96          while (true) {
97 <            long currentBits = value;
98 <            if (unsafe.compareAndSwapLong(this, valueOffset,
99 <                                          currentBits, newBits))
130 <                return longBitsToDouble(currentBits);
97 >            long current = value;
98 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
99 >                return longBitsToDouble(current);
100          }
101      }
102  
103      /**
104       * Atomically sets the value to the given updated value
105 <     * if the current value {@code ==} the expected value.
105 >     * if the current value is <a href="#bitEquals">bitwise equal</a>
106 >     * to the expected value.
107       *
108       * @param expect the expected value
109       * @param update the new value
110 <     * @return true if successful. False return indicates that
111 <     * the actual value was not equal to the expected value.
110 >     * @return {@code true} if successful. False return indicates that
111 >     * the actual value was not bitwise equal to the expected value.
112       */
113      public final boolean compareAndSet(double expect, double update) {
114          return unsafe.compareAndSwapLong(this, valueOffset,
# Line 148 | Line 118 | public class AtomicDouble extends Number
118  
119      /**
120       * Atomically sets the value to the given updated value
121 <     * if the current value {@code ==} the expected value.
121 >     * if the current value is <a href="#bitEquals">bitwise equal</a>
122 >     * to the expected value.
123       *
124       * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
125       * and does not provide ordering guarantees, so is only rarely an
# Line 156 | Line 127 | public class AtomicDouble extends Number
127       *
128       * @param expect the expected value
129       * @param update the new value
130 <     * @return true if successful.
130 >     * @return {@code true} if successful
131       */
132      public final boolean weakCompareAndSet(double expect, double update) {
133          return compareAndSet(expect, update);
# Line 170 | Line 141 | public class AtomicDouble extends Number
141       */
142      public final double getAndAdd(double delta) {
143          while (true) {
144 <            long currentBits = value;
145 <            long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
146 <            if (unsafe.compareAndSwapLong(this, valueOffset,
147 <                                          currentBits, nextBits))
148 <                return longBitsToDouble(currentBits);
144 >            long current = value;
145 >            double currentVal = longBitsToDouble(current);
146 >            double nextVal = currentVal + delta;
147 >            long next = doubleToRawLongBits(nextVal);
148 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
149 >                return currentVal;
150          }
151      }
152  
# Line 185 | Line 157 | public class AtomicDouble extends Number
157       * @return the updated value
158       */
159      public final double addAndGet(double delta) {
160 <        for (;;) {
161 <            double current = get();
162 <            double next = current + delta;
163 <            if (compareAndSet(current, next))
164 <                return next;
160 >        while (true) {
161 >            long current = value;
162 >            double currentVal = longBitsToDouble(current);
163 >            double nextVal = currentVal + delta;
164 >            long next = doubleToRawLongBits(nextVal);
165 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
166 >                return nextVal;
167          }
168      }
169  
170      /**
171       * Returns the String representation of the current value.
172 <     * @return the String representation of the current value.
172 >     * @return the String representation of the current value
173       */
174      public String toString() {
175          return Double.toString(get());
176      }
177  
204
178      /**
179       * Returns the value of this {@code AtomicDouble} as an {@code int}
180       * after a narrowing primitive conversion.
# Line 211 | Line 184 | public class AtomicDouble extends Number
184      }
185  
186      /**
187 <     * Returns the value of this {@code AtomicDouble} as a {@code long}.
187 >     * Returns the value of this {@code AtomicDouble} as a {@code long}
188 >     * after a narrowing primitive conversion.
189       */
190      public long longValue() {
191          return (long)get();
# Line 219 | Line 193 | public class AtomicDouble extends Number
193  
194      /**
195       * Returns the value of this {@code AtomicDouble} as a {@code float}
196 <     * after a widening primitive conversion.
196 >     * after a narrowing primitive conversion.
197       */
198      public float floatValue() {
199          return (float)get();
200      }
201  
202      /**
203 <     * Returns the value of this {@code AtomicDouble} as a {@code double}
230 <     * after a widening primitive conversion.
203 >     * Returns the value of this {@code AtomicDouble} as a {@code double}.
204       */
205      public double doubleValue() {
206          return get();
207      }
208  
209 +    // Unsafe mechanics
210 +    private static final sun.misc.Unsafe unsafe = getUnsafe();
211 +    private static final long valueOffset;
212 +
213 +    static {
214 +        try {
215 +            valueOffset = unsafe.objectFieldOffset
216 +                (AtomicDouble.class.getDeclaredField("value"));
217 +        } catch (Exception ex) { throw new Error(ex); }
218 +    }
219 +
220      /**
221       * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
222       * Replace with a simple call to Unsafe.getUnsafe when integrating
# Line 260 | Line 244 | public class AtomicDouble extends Number
244              }
245          }
246      }
263
247   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines