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
015package com.google.common.util.concurrent;
016
017import static com.google.common.base.Preconditions.checkNotNull;
018import static java.lang.Double.doubleToRawLongBits;
019import static java.lang.Double.longBitsToDouble;
020
021import com.google.common.annotations.GwtIncompatible;
022import com.google.errorprone.annotations.CanIgnoreReturnValue;
023import com.google.j2objc.annotations.ReflectionSupport;
024import java.util.concurrent.atomic.AtomicLongFieldUpdater;
025import java.util.function.DoubleBinaryOperator;
026import java.util.function.DoubleUnaryOperator;
027
028/**
029 * A {@code double} value that may be updated atomically. See the {@link
030 * java.util.concurrent.atomic} package specification for description of the properties of atomic
031 * variables. An {@code AtomicDouble} is used in applications such as atomic accumulation, and
032 * cannot be used as a replacement for a {@link Double}. However, this class does extend {@code
033 * Number} to allow uniform access by tools and utilities that deal with numerically-based classes.
034 *
035 * <p><a id="bitEquals"></a>This class compares primitive {@code double} values in methods such as
036 * {@link #compareAndSet} by comparing their bitwise representation using {@link
037 * Double#doubleToRawLongBits}, which differs from both the primitive double {@code ==} operator and
038 * from {@link Double#equals}, as if implemented by:
039 *
040 * <pre>{@code
041 * static boolean bitEquals(double x, double y) {
042 *   long xBits = Double.doubleToRawLongBits(x);
043 *   long yBits = Double.doubleToRawLongBits(y);
044 *   return xBits == yBits;
045 * }
046 * }</pre>
047 *
048 * <p>It is possible to write a more scalable updater, at the cost of giving up strict atomicity.
049 * See for example <a
050 * href="http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java.base/java/util/concurrent/atomic/DoubleAdder.html">
051 * DoubleAdder</a>.
052 *
053 * @author Doug Lea
054 * @author Martin Buchholz
055 * @since 11.0
056 */
057@GwtIncompatible
058@ReflectionSupport(value = ReflectionSupport.Level.FULL)
059@ElementTypesAreNonnullByDefault
060public class AtomicDouble extends Number implements java.io.Serializable {
061  private static final long serialVersionUID = 0L;
062
063  private transient volatile long value;
064
065  private static final AtomicLongFieldUpdater<AtomicDouble> updater =
066      AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value");
067
068  /**
069   * Creates a new {@code AtomicDouble} with the given initial value.
070   *
071   * @param initialValue the initial value
072   */
073  public AtomicDouble(double initialValue) {
074    value = doubleToRawLongBits(initialValue);
075  }
076
077  /** Creates a new {@code AtomicDouble} with initial value {@code 0.0}. */
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    long next = doubleToRawLongBits(newValue);
108    updater.lazySet(this, next);
109  }
110
111  /**
112   * Atomically sets to the given value and returns the old value.
113   *
114   * @param newValue the new value
115   * @return the previous value
116   */
117  public final double getAndSet(double newValue) {
118    long next = doubleToRawLongBits(newValue);
119    return longBitsToDouble(updater.getAndSet(this, next));
120  }
121
122  /**
123   * Atomically sets the value to the given updated value if the current value is <a
124   * href="#bitEquals">bitwise equal</a> to the expected value.
125   *
126   * @param expect the expected value
127   * @param update the new value
128   * @return {@code true} if successful. False return indicates that the actual value was not
129   *     bitwise equal to the expected value.
130   */
131  public final boolean compareAndSet(double expect, double update) {
132    return updater.compareAndSet(this, doubleToRawLongBits(expect), doubleToRawLongBits(update));
133  }
134
135  /**
136   * Atomically sets the value to the given updated value if the current value is <a
137   * href="#bitEquals">bitwise equal</a> to the expected value.
138   *
139   * <p>May <a
140   * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
141   * fail spuriously</a> and does not provide ordering guarantees, so is only rarely an appropriate
142   * alternative to {@code compareAndSet}.
143   *
144   * @param expect the expected value
145   * @param update the new value
146   * @return {@code true} if successful
147   */
148  public final boolean weakCompareAndSet(double expect, double update) {
149    return updater.weakCompareAndSet(
150        this, doubleToRawLongBits(expect), doubleToRawLongBits(update));
151  }
152
153  /**
154   * Atomically adds the given value to the current value.
155   *
156   * @param delta the value to add
157   * @return the previous value
158   */
159  @CanIgnoreReturnValue
160  public final double getAndAdd(double delta) {
161    return getAndAccumulate(delta, Double::sum);
162  }
163
164  /**
165   * Atomically adds the given value to the current value.
166   *
167   * @param delta the value to add
168   * @return the updated value
169   */
170  @CanIgnoreReturnValue
171  public final double addAndGet(double delta) {
172    return accumulateAndGet(delta, Double::sum);
173  }
174
175  /**
176   * Atomically updates the current value with the results of applying the given function to the
177   * current and given values.
178   *
179   * @param x the update value
180   * @param accumulatorFunction the accumulator function
181   * @return the previous value
182   * @since 31.1
183   */
184  @CanIgnoreReturnValue
185  public final double getAndAccumulate(double x, DoubleBinaryOperator accumulatorFunction) {
186    checkNotNull(accumulatorFunction);
187    return getAndUpdate(oldValue -> accumulatorFunction.applyAsDouble(oldValue, x));
188  }
189
190  /**
191   * Atomically updates the current value with the results of applying the given function to the
192   * current and given values.
193   *
194   * @param x the update value
195   * @param accumulatorFunction the accumulator function
196   * @return the updated value
197   * @since 31.1
198   */
199  @CanIgnoreReturnValue
200  public final double accumulateAndGet(double x, DoubleBinaryOperator accumulatorFunction) {
201    checkNotNull(accumulatorFunction);
202    return updateAndGet(oldValue -> accumulatorFunction.applyAsDouble(oldValue, x));
203  }
204
205  /**
206   * Atomically updates the current value with the results of applying the given function.
207   *
208   * @param updateFunction the update function
209   * @return the previous value
210   * @since 31.1
211   */
212  @CanIgnoreReturnValue
213  public final double getAndUpdate(DoubleUnaryOperator updateFunction) {
214    while (true) {
215      long current = value;
216      double currentVal = longBitsToDouble(current);
217      double nextVal = updateFunction.applyAsDouble(currentVal);
218      long next = doubleToRawLongBits(nextVal);
219      if (updater.compareAndSet(this, current, next)) {
220        return currentVal;
221      }
222    }
223  }
224
225  /**
226   * Atomically updates the current value with the results of applying the given function.
227   *
228   * @param updateFunction the update function
229   * @return the updated value
230   * @since 31.1
231   */
232  @CanIgnoreReturnValue
233  public final double updateAndGet(DoubleUnaryOperator updateFunction) {
234    while (true) {
235      long current = value;
236      double currentVal = longBitsToDouble(current);
237      double nextVal = updateFunction.applyAsDouble(currentVal);
238      long next = doubleToRawLongBits(nextVal);
239      if (updater.compareAndSet(this, current, next)) {
240        return nextVal;
241      }
242    }
243  }
244
245  /**
246   * Returns the String representation of the current value.
247   *
248   * @return the String representation of the current value
249   */
250  @Override
251  public String toString() {
252    return Double.toString(get());
253  }
254
255  /**
256   * Returns the value of this {@code AtomicDouble} as an {@code int} after a narrowing primitive
257   * conversion.
258   */
259  @Override
260  public int intValue() {
261    return (int) get();
262  }
263
264  /**
265   * Returns the value of this {@code AtomicDouble} as a {@code long} after a narrowing primitive
266   * conversion.
267   */
268  @Override
269  public long longValue() {
270    return (long) get();
271  }
272
273  /**
274   * Returns the value of this {@code AtomicDouble} as a {@code float} after a narrowing primitive
275   * conversion.
276   */
277  @Override
278  public float floatValue() {
279    return (float) get();
280  }
281
282  /** Returns the value of this {@code AtomicDouble} as a {@code double}. */
283  @Override
284  public double doubleValue() {
285    return get();
286  }
287
288  /**
289   * Saves the state to a stream (that is, serializes it).
290   *
291   * @serialData The current value is emitted (a {@code double}).
292   */
293  private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
294    s.defaultWriteObject();
295
296    s.writeDouble(get());
297  }
298
299  /** Reconstitutes the instance from a stream (that is, deserializes it). */
300  private void readObject(java.io.ObjectInputStream s)
301      throws java.io.IOException, ClassNotFoundException {
302    s.defaultReadObject();
303
304    set(s.readDouble());
305  }
306}