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