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

Comparing jsr166/src/jsr166e/extra/AtomicDoubleArray.java (file contents):
Revision 1.1 by jsr166, Wed Aug 10 02:03:29 2011 UTC vs.
Revision 1.11 by jsr166, Mon Jul 22 16:47:46 2013 UTC

# Line 14 | Line 14 | import static java.lang.Double.longBitsT
14   * See the {@link java.util.concurrent.atomic} package specification
15   * for description of the properties of atomic variables.
16   *
17 < * <p><a name="bitEquals">This class compares primitive {@code double}
17 > * <p id="bitEquals">This class compares primitive {@code double}
18   * values in methods such as {@link #compareAndSet} by comparing their
19   * bitwise representation using {@link Double#doubleToRawLongBits},
20   * which differs from both the primitive double {@code ==} operator
21   * and from {@link Double#equals}, as if implemented by:
22   *  <pre> {@code
23 < * boolean bitEquals(double x, double y) {
23 > * static boolean bitEquals(double x, double y) {
24   *   long xBits = Double.doubleToRawLongBits(x);
25   *   long yBits = Double.doubleToRawLongBits(y);
26   *   return xBits == yBits;
# Line 32 | Line 32 | import static java.lang.Double.longBitsT
32   public class AtomicDoubleArray implements java.io.Serializable {
33      private static final long serialVersionUID = -2308431214976778248L;
34  
35 <    private final long[] array;
35 >    private final transient long[] array;
36  
37      private long checkedByteOffset(int i) {
38          if (i < 0 || i >= array.length)
# Line 162 | Line 162 | public class AtomicDoubleArray implement
162       * if the current value is <a href="#bitEquals">bitwise equal</a>
163       * to the expected value.
164       *
165 <     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
166 <     * and does not provide ordering guarantees, so is only rarely an
167 <     * appropriate alternative to {@code compareAndSet}.
165 >     * <p><a
166 >     * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
167 >     * May fail spuriously and does not provide ordering guarantees</a>,
168 >     * so is only rarely an appropriate alternative to {@code compareAndSet}.
169       *
170       * @param i the index
171       * @param expect the expected value
# Line 222 | Line 223 | public class AtomicDoubleArray implement
223          if (iMax == -1)
224              return "[]";
225  
226 <        StringBuilder b = new StringBuilder();
226 >        // Double.toString(Math.PI).length() == 17
227 >        StringBuilder b = new StringBuilder((17 + 2) * (iMax + 1));
228          b.append('[');
229 <        for (int i = 0; ; i++) {
229 >        for (int i = 0;; i++) {
230              b.append(longBitsToDouble(getRaw(byteOffset(i))));
231              if (i == iMax)
232                  return b.append(']').toString();
# Line 232 | Line 234 | public class AtomicDoubleArray implement
234          }
235      }
236  
237 +    /**
238 +     * Saves the state to a stream (that is, serializes it).
239 +     *
240 +     * @param s the stream
241 +     * @throws java.io.IOException if an I/O error occurs
242 +     * @serialData The length of the array is emitted (int), followed by all
243 +     *             of its elements (each a {@code double}) in the proper order.
244 +     */
245 +    private void writeObject(java.io.ObjectOutputStream s)
246 +        throws java.io.IOException {
247 +        s.defaultWriteObject();
248 +
249 +        // Write out array length
250 +        int length = length();
251 +        s.writeInt(length);
252 +
253 +        // Write out all elements in the proper order.
254 +        for (int i = 0; i < length; i++)
255 +            s.writeDouble(get(i));
256 +    }
257 +
258 +    /**
259 +     * Reconstitutes the instance from a stream (that is, deserializes it).
260 +     * @param s the stream
261 +     * @throws ClassNotFoundException if the class of a serialized object
262 +     *         could not be found
263 +     * @throws java.io.IOException if an I/O error occurs
264 +     */
265 +    private void readObject(java.io.ObjectInputStream s)
266 +        throws java.io.IOException, ClassNotFoundException {
267 +        s.defaultReadObject();
268 +
269 +        // Read in array length and allocate array
270 +        int length = s.readInt();
271 +        unsafe.putObjectVolatile(this, arrayOffset, new long[length]);
272 +
273 +        // Read in all elements in the proper order.
274 +        for (int i = 0; i < length; i++)
275 +            set(i, s.readDouble());
276 +    }
277 +
278      // Unsafe mechanics
279      private static final sun.misc.Unsafe unsafe = getUnsafe();
280 +    private static final long arrayOffset;
281      private static final int base = unsafe.arrayBaseOffset(long[].class);
282      private static final int shift;
283  
284      static {
285 <        int scale = unsafe.arrayIndexScale(long[].class);
286 <        if ((scale & (scale - 1)) != 0)
287 <            throw new Error("data type scale not a power of two");
288 <        shift = 31 - Integer.numberOfLeadingZeros(scale);
285 >        try {
286 >            Class<?> k = AtomicDoubleArray.class;
287 >            arrayOffset = unsafe.objectFieldOffset
288 >                (k.getDeclaredField("array"));
289 >            int scale = unsafe.arrayIndexScale(long[].class);
290 >            if ((scale & (scale - 1)) != 0)
291 >                throw new Error("data type scale not a power of two");
292 >            shift = 31 - Integer.numberOfLeadingZeros(scale);
293 >        } catch (Exception e) {
294 >            throw new Error(e);
295 >        }
296      }
297  
298      /**
# Line 254 | Line 305 | public class AtomicDoubleArray implement
305      private static sun.misc.Unsafe getUnsafe() {
306          try {
307              return sun.misc.Unsafe.getUnsafe();
308 <        } catch (SecurityException se) {
309 <            try {
310 <                return java.security.AccessController.doPrivileged
311 <                    (new java.security
312 <                     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
313 <                        public sun.misc.Unsafe run() throws Exception {
314 <                            java.lang.reflect.Field f = sun.misc
315 <                                .Unsafe.class.getDeclaredField("theUnsafe");
316 <                            f.setAccessible(true);
317 <                            return (sun.misc.Unsafe) f.get(null);
318 <                        }});
319 <            } catch (java.security.PrivilegedActionException e) {
320 <                throw new RuntimeException("Could not initialize intrinsics",
321 <                                           e.getCause());
322 <            }
308 >        } catch (SecurityException tryReflectionInstead) {}
309 >        try {
310 >            return java.security.AccessController.doPrivileged
311 >            (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
312 >                public sun.misc.Unsafe run() throws Exception {
313 >                    Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
314 >                    for (java.lang.reflect.Field f : k.getDeclaredFields()) {
315 >                        f.setAccessible(true);
316 >                        Object x = f.get(null);
317 >                        if (k.isInstance(x))
318 >                            return k.cast(x);
319 >                    }
320 >                    throw new NoSuchFieldError("the Unsafe");
321 >                }});
322 >        } catch (java.security.PrivilegedActionException e) {
323 >            throw new RuntimeException("Could not initialize intrinsics",
324 >                                       e.getCause());
325          }
326      }
327   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines