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    }