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