    001    /*
    002     * Written by Doug Lea and Martin Buchholz with assistance from
    003     * members of JCP JSR-166 Expert Group and released to the public
    004     * domain, as explained at
    005     * http://creativecommons.org/publicdomain/zero/1.0/
    006     */
    007
    008    /*
    009     * Source:
    010     * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDouble.java?revision=1.13
    011     * (Modified to adapt to guava coding conventions and
    012     * to use AtomicLongFieldUpdater instead of sun.misc.Unsafe)
    013     */
    014
    015    package com.google.common.util.concurrent;
    016
    017    import static java.lang.Double.doubleToRawLongBits;
    018    import static java.lang.Double.longBitsToDouble;
    019
    020    import com.google.common.annotations.Beta;
    021
    022    import java.util.concurrent.atomic.AtomicLongFieldUpdater;
    023
    024    /**
    025     * A {@code double} value that may be updated atomically.  See the
    026     * {@link java.util.concurrent.atomic} package specification for
    027     * description of the properties of atomic variables.  An {@code
    028     * AtomicDouble} is used in applications such as atomic accumulation,
    029     * and cannot be used as a replacement for a {@link Double}.  However,
    030     * this class does extend {@code Number} to allow uniform access by
    031     * tools and utilities that deal with numerically-based classes.
    032     *
    033     * <p><a name="bitEquals">This class compares primitive {@code double}
    034     * values in methods such as {@link #compareAndSet} by comparing their
    035     * bitwise representation using {@link Double#doubleToRawLongBits},
    036     * which differs from both the primitive double {@code ==} operator
    037     * and from {@link Double#equals}, as if implemented by:
    038     *  <pre> {@code
    039     * static boolean bitEquals(double x, double y) {
    040     *   long xBits = Double.doubleToRawLongBits(x);
    041     *   long yBits = Double.doubleToRawLongBits(y);
    042     *   return xBits == yBits;
    043     * }}</pre>
    044     *
    045     * <p>It is possible to write a more scalable updater, at the cost of
    046     * giving up strict atomicity.  See for example
    047     * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleAdder.html"
    048     * DoubleAdder>
    049     * and
    050     * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleMaxUpdater.html"
    051     * DoubleMaxUpdater>.
    052     *
    053     * @author Doug Lea
    054     * @author Martin Buchholz
    055     * @since 11.0
    056     */
    057    @Beta
    058    public class AtomicDouble extends Number implements java.io.Serializable {
    059      private static final long serialVersionUID = 0L;
    060
    061      private transient volatile long value;
    062
    063      private static final AtomicLongFieldUpdater<AtomicDouble> updater =
    064          AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value");
    065
    066      /**
    067       * Creates a new {@code AtomicDouble} with the given initial value.
    068       *
    069       * @param initialValue the initial value
    070       */
    071      public AtomicDouble(double initialValue) {
    072        value = doubleToRawLongBits(initialValue);
    073      }
    074
    075      /**
    076       * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
    077       */
    078      public AtomicDouble() {
    079        // assert doubleToRawLongBits(0.0) == 0L;
    080      }
    081
    082      /**
    083       * Gets the current value.
    084       *
    085       * @return the current value
    086       */
    087      public final double get() {
    088        return longBitsToDouble(value);
    089      }
    090
    091      /**
    092       * Sets to the given value.
    093       *
    094       * @param newValue the new value
    095       */
    096      public final void set(double newValue) {
    097        long next = doubleToRawLongBits(newValue);
    098        value = next;
    099      }
    100
    101      /**
    102       * Eventually sets to the given value.
    103       *
    104       * @param newValue the new value
    105       */
    106      public final void lazySet(double newValue) {
    107        set(newValue);
    108        // TODO(user): replace with code below when jdk5 support is dropped.
    109        // long next = doubleToRawLongBits(newValue);
    110        // updater.lazySet(this, next);
    111      }
    112
    113      /**
    114       * Atomically sets to the given value and returns the old value.
    115       *
    116       * @param newValue the new value
    117       * @return the previous value
    118       */
    119      public final double getAndSet(double newValue) {
    120        long next = doubleToRawLongBits(newValue);
    121        return longBitsToDouble(updater.getAndSet(this, next));
    122      }
    123
    124      /**
    125       * Atomically sets the value to the given updated value
    126       * if the current value is <a href="#bitEquals">bitwise equal</a>
    127       * to the expected value.
    128       *
    129       * @param expect the expected value
    130       * @param update the new value
    131       * @return {@code true} if successful. False return indicates that
    132       * the actual value was not bitwise equal to the expected value.
    133       */
    134      public final boolean compareAndSet(double expect, double update) {
    135        return updater.compareAndSet(this,
    136                                     doubleToRawLongBits(expect),
    137                                     doubleToRawLongBits(update));
    138      }
    139
    140      /**
    141       * Atomically sets the value to the given updated value
    142       * if the current value is <a href="#bitEquals">bitwise equal</a>
    143       * to the expected value.
    144       *
    145       * <p>May <a
    146       * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
    147       * fail spuriously</a>
    148       * and does not provide ordering guarantees, so is only rarely an
    149       * appropriate alternative to {@code compareAndSet}.
    150       *
    151       * @param expect the expected value
    152       * @param update the new value
    153       * @return {@code true} if successful
    154       */
    155      public final boolean weakCompareAndSet(double expect, double update) {
    156        return updater.weakCompareAndSet(this,
    157                                         doubleToRawLongBits(expect),
    158                                         doubleToRawLongBits(update));
    159      }
    160
    161      /**
    162       * Atomically adds the given value to the current value.
    163       *
    164       * @param delta the value to add
    165       * @return the previous value
    166       */
    167      public final double getAndAdd(double delta) {
    168        while (true) {
    169          long current = value;
    170          double currentVal = longBitsToDouble(current);
    171          double nextVal = currentVal + delta;
    172          long next = doubleToRawLongBits(nextVal);
    173          if (updater.compareAndSet(this, current, next)) {
    174            return currentVal;
    175          }
    176        }
    177      }
    178
    179      /**
    180       * Atomically adds the given value to the current value.
    181       *
    182       * @param delta the value to add
    183       * @return the updated value
    184       */
    185      public final double addAndGet(double delta) {
    186        while (true) {
    187          long current = value;
    188          double currentVal = longBitsToDouble(current);
    189          double nextVal = currentVal + delta;
    190          long next = doubleToRawLongBits(nextVal);
    191          if (updater.compareAndSet(this, current, next)) {
    192            return nextVal;
    193          }
    194        }
    195      }
    196
    197      /**
    198       * Returns the String representation of the current value.
    199       * @return the String representation of the current value
    200       */
    201      public String toString() {
    202        return Double.toString(get());
    203      }
    204
    205      /**
    206       * Returns the value of this {@code AtomicDouble} as an {@code int}
    207       * after a narrowing primitive conversion.
    208       */
    209      public int intValue() {
    210        return (int) get();
    211      }
    212
    213      /**
    214       * Returns the value of this {@code AtomicDouble} as a {@code long}
    215       * after a narrowing primitive conversion.
    216       */
    217      public long longValue() {
    218        return (long) get();
    219      }
    220
    221      /**
    222       * Returns the value of this {@code AtomicDouble} as a {@code float}
    223       * after a narrowing primitive conversion.
    224       */
    225      public float floatValue() {
    226        return (float) get();
    227      }
    228
    229      /**
    230       * Returns the value of this {@code AtomicDouble} as a {@code double}.
    231       */
    232      public double doubleValue() {
    233        return get();
    234      }
    235
    236      /**
    237       * Saves the state to a stream (that is, serializes it).
    238       *
    239       * @serialData The current value is emitted (a {@code double}).
    240       */
    241      private void writeObject(java.io.ObjectOutputStream s)
    242          throws java.io.IOException {
    243        s.defaultWriteObject();
    244
    245        s.writeDouble(get());
    246      }
    247
    248      /**
    249       * Reconstitutes the instance from a stream (that is, deserializes it).
    250       */
    251      private void readObject(java.io.ObjectInputStream s)
    252          throws java.io.IOException, ClassNotFoundException {
    253        s.defaultReadObject();
    254
    255        set(s.readDouble());
    256      }
    257    }