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.3 by jsr166, Tue Aug 9 08:28:54 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   import static java.lang.Double.doubleToRawLongBits;
10   import static java.lang.Double.longBitsToDouble;
10 import sun.misc.Unsafe;
11  
12   /**
13   * A {@code double} value that may be updated atomically.  See the
14   * {@link java.util.concurrent.atomic} package specification for
15 < * description of the properties of atomic variables. An
16 < * {@code AtomicDouble} is used in applications such as atomically
17 < * incremented sequence numbers, and cannot be used as a replacement
18 < * for a {@link java.lang.Double}. However, this class does extend
19 < * {@code Number} to allow uniform access by tools and utilities that
20 < * deal with numerically-based classes.
15 > * description of the properties of atomic variables.  An {@code
16 > * AtomicDouble} is used in applications such as atomic accumulation,
17 > * and cannot be used as a replacement for a {@link Double}.  However,
18 > * this class does extend {@code Number} to allow uniform access by
19 > * tools and utilities that deal with numerically-based classes.
20 > *
21 > * <p>This class differs from the primitive double {@code ==} operator
22 > * and from {@link Double#equals} in that it uses purely bitwise
23 > * equality in methods such as {@link #compareAndSet}, as if
24 > * implemented by:
25 > *  <pre> {@code
26 > * boolean bitEquals(double x, double y) {
27 > *   long xBits = Double.doubleToRawLongBits(x);
28 > *   long yBits = Double.doubleToRawLongBits(y);
29 > *   return xBits == yBits;
30 > * }}</pre>
31   *
22 * @since 1.5
32   * @author Doug Lea
33 + * @author Martin Buchholz
34   */
35   public class AtomicDouble extends Number implements java.io.Serializable {
36 <    private static final long serialVersionUID = 1927816293512124184L;
36 >    static final long serialVersionUID = -8405198993435143622L;
37  
38      // setup to use Unsafe.compareAndSwapLong for updates
39 <    private static final Unsafe unsafe = Unsafe.getUnsafe();
39 >    private static final sun.misc.Unsafe unsafe = getUnsafe();
40      private static final long valueOffset;
41  
42      /**
# Line 41 | Line 51 | public class AtomicDouble extends Number
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 native boolean VMSupportsCS8();
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 {
# Line 88 | Line 110 | public class AtomicDouble extends Number
110       * Eventually sets to the given value.
111       *
112       * @param newValue the new value
91     * @since 1.6
113       */
114      public final void lazySet(double newValue) {
115          unsafe.putOrderedLong(this, valueOffset, doubleToRawLongBits(newValue));
# Line 104 | Line 125 | public class AtomicDouble extends Number
125          long newBits = doubleToRawLongBits(newValue);
126          while (true) {
127              long currentBits = value;
128 <            if (compareAndSet(currentBits, newBits))
128 >            if (unsafe.compareAndSwapLong(this, valueOffset,
129 >                                          currentBits, newBits))
130                  return longBitsToDouble(currentBits);
131          }
132      }
# Line 150 | Line 172 | public class AtomicDouble extends Number
172          while (true) {
173              long currentBits = value;
174              long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
175 <            if (compareAndSet(currentBits, nextBits))
175 >            if (unsafe.compareAndSwapLong(this, valueOffset,
176 >                                          currentBits, nextBits))
177                  return longBitsToDouble(currentBits);
178          }
179      }
# Line 210 | Line 233 | public class AtomicDouble extends Number
233          return get();
234      }
235  
236 +    /**
237 +     * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
238 +     * Replace with a simple call to Unsafe.getUnsafe when integrating
239 +     * into a jdk.
240 +     *
241 +     * @return a sun.misc.Unsafe
242 +     */
243 +    private static sun.misc.Unsafe getUnsafe() {
244 +        try {
245 +            return sun.misc.Unsafe.getUnsafe();
246 +        } catch (SecurityException se) {
247 +            try {
248 +                return java.security.AccessController.doPrivileged
249 +                    (new java.security
250 +                     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
251 +                        public sun.misc.Unsafe run() throws Exception {
252 +                            java.lang.reflect.Field f = sun.misc
253 +                                .Unsafe.class.getDeclaredField("theUnsafe");
254 +                            f.setAccessible(true);
255 +                            return (sun.misc.Unsafe) f.get(null);
256 +                        }});
257 +            } catch (java.security.PrivilegedActionException e) {
258 +                throw new RuntimeException("Could not initialize intrinsics",
259 +                                           e.getCause());
260 +            }
261 +        }
262 +    }
263 +
264   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines