View Javadoc
1   /*
2    * Written by Doug Lea and Martin Buchholz with assistance from
3    * members of JCP JSR-166 Expert Group and released to the public
4    * domain, as explained at
5    * http://creativecommons.org/publicdomain/zero/1.0/
6    */
7   
8   /*
9    * Source:
10   * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDouble.java?revision=1.13
11   * (Modified to adapt to guava coding conventions and
12   * to use AtomicLongFieldUpdater instead of sun.misc.Unsafe)
13   */
14  
15  package com.google.common.util.concurrent;
16  
17  import static java.lang.Double.doubleToRawLongBits;
18  import static java.lang.Double.longBitsToDouble;
19  
20  import com.google.common.annotations.GwtIncompatible;
21  import com.google.errorprone.annotations.CanIgnoreReturnValue;
22  import com.google.j2objc.annotations.ReflectionSupport;
23  import java.util.concurrent.atomic.AtomicLongFieldUpdater;
24  
25  /**
26   * A {@code double} value that may be updated atomically. See the {@link
27   * java.util.concurrent.atomic} package specification for description of the properties of atomic
28   * variables. An {@code AtomicDouble} is used in applications such as atomic accumulation, and
29   * cannot be used as a replacement for a {@link Double}. However, this class does extend {@code
30   * Number} to allow uniform access by tools and utilities that deal with numerically-based classes.
31   *
32   * <p><a name="bitEquals"></a>This class compares primitive {@code double} values in methods such as
33   * {@link #compareAndSet} by comparing their bitwise representation using {@link
34   * Double#doubleToRawLongBits}, which differs from both the primitive double {@code ==} operator and
35   * from {@link Double#equals}, as if implemented by:
36   *
37   * <pre>{@code
38   * static boolean bitEquals(double x, double y) {
39   *   long xBits = Double.doubleToRawLongBits(x);
40   *   long yBits = Double.doubleToRawLongBits(y);
41   *   return xBits == yBits;
42   * }
43   * }</pre>
44   *
45   * <p>It is possible to write a more scalable updater, at the cost of giving up strict atomicity.
46   * See for example <a
47   * href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleAdder.html">
48   * DoubleAdder</a> and <a
49   * href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleMaxUpdater.html">
50   * DoubleMaxUpdater</a>.
51   *
52   * @author Doug Lea
53   * @author Martin Buchholz
54   * @since 11.0
55   */
56  @GwtIncompatible
57  @ReflectionSupport(value = ReflectionSupport.Level.FULL)
58  public class AtomicDouble extends Number implements java.io.Serializable {
59    private static final long serialVersionUID = 0L;
60  
61    private transient volatile long value;
62  
63    private static final AtomicLongFieldUpdater<AtomicDouble> updater =
64        AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value");
65  
66    /**
67     * Creates a new {@code AtomicDouble} with the given initial value.
68     *
69     * @param initialValue the initial value
70     */
71    public AtomicDouble(double initialValue) {
72      value = doubleToRawLongBits(initialValue);
73    }
74  
75    /**
76     * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
77     */
78    public AtomicDouble() {
79      // assert doubleToRawLongBits(0.0) == 0L;
80    }
81  
82    /**
83     * Gets the current value.
84     *
85     * @return the current value
86     */
87    public final double get() {
88      return longBitsToDouble(value);
89    }
90  
91    /**
92     * Sets to the given value.
93     *
94     * @param newValue the new value
95     */
96    public final void set(double newValue) {
97      long next = doubleToRawLongBits(newValue);
98      value = next;
99    }
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   @CanIgnoreReturnValue
168   public final double getAndAdd(double delta) {
169     while (true) {
170       long current = value;
171       double currentVal = longBitsToDouble(current);
172       double nextVal = currentVal + delta;
173       long next = doubleToRawLongBits(nextVal);
174       if (updater.compareAndSet(this, current, next)) {
175         return currentVal;
176       }
177     }
178   }
179 
180   /**
181    * Atomically adds the given value to the current value.
182    *
183    * @param delta the value to add
184    * @return the updated value
185    */
186   @CanIgnoreReturnValue
187   public final double addAndGet(double delta) {
188     while (true) {
189       long current = value;
190       double currentVal = longBitsToDouble(current);
191       double nextVal = currentVal + delta;
192       long next = doubleToRawLongBits(nextVal);
193       if (updater.compareAndSet(this, current, next)) {
194         return nextVal;
195       }
196     }
197   }
198 
199   /**
200    * Returns the String representation of the current value.
201    * @return the String representation of the current value
202    */
203   public String toString() {
204     return Double.toString(get());
205   }
206 
207   /**
208    * Returns the value of this {@code AtomicDouble} as an {@code int}
209    * after a narrowing primitive conversion.
210    */
211   public int intValue() {
212     return (int) get();
213   }
214 
215   /**
216    * Returns the value of this {@code AtomicDouble} as a {@code long}
217    * after a narrowing primitive conversion.
218    */
219   public long longValue() {
220     return (long) get();
221   }
222 
223   /**
224    * Returns the value of this {@code AtomicDouble} as a {@code float}
225    * after a narrowing primitive conversion.
226    */
227   public float floatValue() {
228     return (float) get();
229   }
230 
231   /**
232    * Returns the value of this {@code AtomicDouble} as a {@code double}.
233    */
234   public double doubleValue() {
235     return get();
236   }
237 
238   /**
239    * Saves the state to a stream (that is, serializes it).
240    *
241    * @serialData The current value is emitted (a {@code double}).
242    */
243   private void writeObject(java.io.ObjectOutputStream s)
244       throws java.io.IOException {
245     s.defaultWriteObject();
246 
247     s.writeDouble(get());
248   }
249 
250   /**
251    * Reconstitutes the instance from a stream (that is, deserializes it).
252    */
253   private void readObject(java.io.ObjectInputStream s)
254       throws java.io.IOException, ClassNotFoundException {
255     s.defaultReadObject();
256 
257     set(s.readDouble());
258   }
259 }