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.5 by jsr166, Wed Aug 10 01:29:45 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 35 | Line 37 | import static java.lang.Double.longBitsT
37   public class AtomicDouble extends Number implements java.io.Serializable {
38      static final long serialVersionUID = -8405198993435143622L;
39  
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    }
48
40      private volatile long value;
41  
42      /**
# Line 77 | Line 68 | public class AtomicDouble extends Number
68       * @param newValue the new value
69       */
70      public final void set(double newValue) {
71 <        value = doubleToRawLongBits(newValue);
71 >        long next = doubleToRawLongBits(newValue);
72 >        value = next;
73      }
74  
75      /**
# Line 86 | Line 78 | public class AtomicDouble extends Number
78       * @param newValue the new value
79       */
80      public final void lazySet(double newValue) {
81 <        unsafe.putOrderedLong(this, valueOffset, doubleToRawLongBits(newValue));
81 >        long next = doubleToRawLongBits(newValue);
82 >        unsafe.putOrderedLong(this, valueOffset, next);
83      }
84  
85      /**
# Line 96 | Line 89 | public class AtomicDouble extends Number
89       * @return the previous value
90       */
91      public final double getAndSet(double newValue) {
92 <        long newBits = doubleToRawLongBits(newValue);
92 >        long next = doubleToRawLongBits(newValue);
93          while (true) {
94 <            long currentBits = value;
95 <            if (unsafe.compareAndSwapLong(this, valueOffset,
96 <                                          currentBits, newBits))
104 <                return longBitsToDouble(currentBits);
94 >            long current = value;
95 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
96 >                return longBitsToDouble(current);
97          }
98      }
99  
100      /**
101       * Atomically sets the value to the given updated value
102 <     * if the current value {@code ==} the expected value.
102 >     * if the current value is <a href="#bitEquals">bitwise equal</a>
103 >     * to the expected value.
104       *
105       * @param expect the expected value
106       * @param update the new value
107 <     * @return true if successful. False return indicates that
108 <     * the actual value was not equal to the expected value.
107 >     * @return {@code true} if successful. False return indicates that
108 >     * the actual value was not bitwise equal to the expected value.
109       */
110      public final boolean compareAndSet(double expect, double update) {
111          return unsafe.compareAndSwapLong(this, valueOffset,
# Line 122 | Line 115 | public class AtomicDouble extends Number
115  
116      /**
117       * Atomically sets the value to the given updated value
118 <     * if the current value {@code ==} the expected value.
118 >     * if the current value is <a href="#bitEquals">bitwise equal</a>
119 >     * to the expected value.
120       *
121       * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
122       * and does not provide ordering guarantees, so is only rarely an
# Line 130 | Line 124 | public class AtomicDouble extends Number
124       *
125       * @param expect the expected value
126       * @param update the new value
127 <     * @return true if successful.
127 >     * @return {@code true} if successful
128       */
129      public final boolean weakCompareAndSet(double expect, double update) {
130          return compareAndSet(expect, update);
# Line 144 | Line 138 | public class AtomicDouble extends Number
138       */
139      public final double getAndAdd(double delta) {
140          while (true) {
141 <            long currentBits = value;
142 <            long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
143 <            if (unsafe.compareAndSwapLong(this, valueOffset,
144 <                                          currentBits, nextBits))
145 <                return longBitsToDouble(currentBits);
141 >            long current = value;
142 >            double currentVal = longBitsToDouble(current);
143 >            double nextVal = currentVal + delta;
144 >            long next = doubleToRawLongBits(nextVal);
145 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
146 >                return currentVal;
147          }
148      }
149  
# Line 159 | Line 154 | public class AtomicDouble extends Number
154       * @return the updated value
155       */
156      public final double addAndGet(double delta) {
157 <        for (;;) {
158 <            double current = get();
159 <            double next = current + delta;
160 <            if (compareAndSet(current, next))
161 <                return next;
157 >        while (true) {
158 >            long current = value;
159 >            double currentVal = longBitsToDouble(current);
160 >            double nextVal = currentVal + delta;
161 >            long next = doubleToRawLongBits(nextVal);
162 >            if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
163 >                return nextVal;
164          }
165      }
166  
167      /**
168       * Returns the String representation of the current value.
169 <     * @return the String representation of the current value.
169 >     * @return the String representation of the current value
170       */
171      public String toString() {
172          return Double.toString(get());
173      }
174  
178
175      /**
176       * Returns the value of this {@code AtomicDouble} as an {@code int}
177       * after a narrowing primitive conversion.
# Line 185 | Line 181 | public class AtomicDouble extends Number
181      }
182  
183      /**
184 <     * Returns the value of this {@code AtomicDouble} as a {@code long}.
184 >     * Returns the value of this {@code AtomicDouble} as a {@code long}
185 >     * after a narrowing primitive conversion.
186       */
187      public long longValue() {
188          return (long)get();
# Line 193 | Line 190 | public class AtomicDouble extends Number
190  
191      /**
192       * Returns the value of this {@code AtomicDouble} as a {@code float}
193 <     * after a widening primitive conversion.
193 >     * after a narrowing primitive conversion.
194       */
195      public float floatValue() {
196          return (float)get();
197      }
198  
199      /**
200 <     * Returns the value of this {@code AtomicDouble} as a {@code double}
204 <     * after a widening primitive conversion.
200 >     * Returns the value of this {@code AtomicDouble} as a {@code double}.
201       */
202      public double doubleValue() {
203          return get();
204      }
205  
206 +    // Unsafe mechanics
207 +    private static final sun.misc.Unsafe unsafe = getUnsafe();
208 +    private static final long valueOffset;
209 +
210 +    static {
211 +        try {
212 +            valueOffset = unsafe.objectFieldOffset
213 +                (AtomicDouble.class.getDeclaredField("value"));
214 +        } catch (Exception ex) { throw new Error(ex); }
215 +    }
216 +
217      /**
218       * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
219       * Replace with a simple call to Unsafe.getUnsafe when integrating

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines