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 static java.lang.Double.doubleToRawLongBits;
018 import static java.lang.Double.longBitsToDouble;
019
020 import com.google.common.annotations.Beta;
021
022 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
023
024 /**
025 * A {@code double} value that may be updated atomically. See the
026 * {@link java.util.concurrent.atomic} package specification for
027 * description of the properties of atomic variables. An {@code
028 * AtomicDouble} is used in applications such as atomic accumulation,
029 * and cannot be used as a replacement for a {@link Double}. However,
030 * this class does extend {@code Number} to allow uniform access by
031 * tools and utilities that deal with numerically-based classes.
032 *
033 * <p><a name="bitEquals">This class compares primitive {@code double}
034 * values in methods such as {@link #compareAndSet} by comparing their
035 * bitwise representation using {@link Double#doubleToRawLongBits},
036 * which differs from both the primitive double {@code ==} operator
037 * and from {@link Double#equals}, as if implemented by:
038 * <pre> {@code
039 * static boolean bitEquals(double x, double y) {
040 * long xBits = Double.doubleToRawLongBits(x);
041 * long yBits = Double.doubleToRawLongBits(y);
042 * return xBits == yBits;
043 * }}</pre>
044 *
045 * <p>It is possible to write a more scalable updater, at the cost of
046 * giving up strict atomicity. See for example
047 * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleAdder.html"
048 * DoubleAdder>
049 * and
050 * <a href="http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/DoubleMaxUpdater.html"
051 * DoubleMaxUpdater>.
052 *
053 * @author Doug Lea
054 * @author Martin Buchholz
055 * @since 11.0
056 */
057 @Beta
058 public class AtomicDouble extends Number implements java.io.Serializable {
059 private static final long serialVersionUID = 0L;
060
061 private transient volatile long value;
062
063 private static final AtomicLongFieldUpdater<AtomicDouble> updater =
064 AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value");
065
066 /**
067 * Creates a new {@code AtomicDouble} with the given initial value.
068 *
069 * @param initialValue the initial value
070 */
071 public AtomicDouble(double initialValue) {
072 value = doubleToRawLongBits(initialValue);
073 }
074
075 /**
076 * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
077 */
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 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 public final double getAndAdd(double delta) {
168 while (true) {
169 long current = value;
170 double currentVal = longBitsToDouble(current);
171 double nextVal = currentVal + delta;
172 long next = doubleToRawLongBits(nextVal);
173 if (updater.compareAndSet(this, current, next)) {
174 return currentVal;
175 }
176 }
177 }
178
179 /**
180 * Atomically adds the given value to the current value.
181 *
182 * @param delta the value to add
183 * @return the updated value
184 */
185 public final double addAndGet(double delta) {
186 while (true) {
187 long current = value;
188 double currentVal = longBitsToDouble(current);
189 double nextVal = currentVal + delta;
190 long next = doubleToRawLongBits(nextVal);
191 if (updater.compareAndSet(this, current, next)) {
192 return nextVal;
193 }
194 }
195 }
196
197 /**
198 * Returns the String representation of the current value.
199 * @return the String representation of the current value
200 */
201 public String toString() {
202 return Double.toString(get());
203 }
204
205 /**
206 * Returns the value of this {@code AtomicDouble} as an {@code int}
207 * after a narrowing primitive conversion.
208 */
209 public int intValue() {
210 return (int) get();
211 }
212
213 /**
214 * Returns the value of this {@code AtomicDouble} as a {@code long}
215 * after a narrowing primitive conversion.
216 */
217 public long longValue() {
218 return (long) get();
219 }
220
221 /**
222 * Returns the value of this {@code AtomicDouble} as a {@code float}
223 * after a narrowing primitive conversion.
224 */
225 public float floatValue() {
226 return (float) get();
227 }
228
229 /**
230 * Returns the value of this {@code AtomicDouble} as a {@code double}.
231 */
232 public double doubleValue() {
233 return get();
234 }
235
236 /**
237 * Saves the state to a stream (that is, serializes it).
238 *
239 * @serialData The current value is emitted (a {@code double}).
240 */
241 private void writeObject(java.io.ObjectOutputStream s)
242 throws java.io.IOException {
243 s.defaultWriteObject();
244
245 s.writeDouble(get());
246 }
247
248 /**
249 * Reconstitutes the instance from a stream (that is, deserializes it).
250 */
251 private void readObject(java.io.ObjectInputStream s)
252 throws java.io.IOException, ClassNotFoundException {
253 s.defaultReadObject();
254
255 set(s.readDouble());
256 }
257 }