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