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