ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.19
Committed: Mon Jul 22 16:47:46 2013 UTC (10 years, 9 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +6 -0 lines
Log Message:
fix javadoc warnings for serialization methods

File Contents

# Content
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 package jsr166e.extra;
9
10 import static java.lang.Double.doubleToRawLongBits;
11 import static java.lang.Double.longBitsToDouble;
12
13 /**
14 * A {@code double} value that may be updated atomically. See the
15 * {@link java.util.concurrent.atomic} package specification for
16 * description of the properties of atomic variables. An {@code
17 * AtomicDouble} is used in applications such as atomic accumulation,
18 * and cannot be used as a replacement for a {@link Double}. However,
19 * this class does extend {@code Number} to allow uniform access by
20 * tools and utilities that deal with numerically-based classes.
21 *
22 * <p id="bitEquals">This class compares primitive {@code double}
23 * values in methods such as {@link #compareAndSet} by comparing their
24 * bitwise representation using {@link Double#doubleToRawLongBits},
25 * which differs from both the primitive double {@code ==} operator
26 * and from {@link Double#equals}, as if implemented by:
27 * <pre> {@code
28 * static boolean bitEquals(double x, double y) {
29 * long xBits = Double.doubleToRawLongBits(x);
30 * long yBits = Double.doubleToRawLongBits(y);
31 * return xBits == yBits;
32 * }}</pre>
33 *
34 * @see jsr166e.DoubleAdder
35 * @see jsr166e.DoubleMaxUpdater
36 *
37 * @author Doug Lea
38 * @author Martin Buchholz
39 */
40 public class AtomicDouble extends Number implements java.io.Serializable {
41 private static final long serialVersionUID = -8405198993435143622L;
42
43 private transient volatile long value;
44
45 /**
46 * Creates a new {@code AtomicDouble} with the given initial value.
47 *
48 * @param initialValue the initial value
49 */
50 public AtomicDouble(double initialValue) {
51 value = doubleToRawLongBits(initialValue);
52 }
53
54 /**
55 * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
56 */
57 public AtomicDouble() {
58 // assert doubleToRawLongBits(0.0) == 0L;
59 }
60
61 /**
62 * Gets the current value.
63 *
64 * @return the current value
65 */
66 public final double get() {
67 return longBitsToDouble(value);
68 }
69
70 /**
71 * Sets to the given value.
72 *
73 * @param newValue the new value
74 */
75 public final void set(double newValue) {
76 long next = doubleToRawLongBits(newValue);
77 value = next;
78 }
79
80 /**
81 * Eventually sets to the given value.
82 *
83 * @param newValue the new value
84 */
85 public final void lazySet(double newValue) {
86 long next = doubleToRawLongBits(newValue);
87 unsafe.putOrderedLong(this, valueOffset, next);
88 }
89
90 /**
91 * Atomically sets to the given value and returns the old value.
92 *
93 * @param newValue the new value
94 * @return the previous value
95 */
96 public final double getAndSet(double newValue) {
97 long next = doubleToRawLongBits(newValue);
98 while (true) {
99 long current = value;
100 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
101 return longBitsToDouble(current);
102 }
103 }
104
105 /**
106 * Atomically sets the value to the given updated value
107 * if the current value is <a href="#bitEquals">bitwise equal</a>
108 * to the expected value.
109 *
110 * @param expect the expected value
111 * @param update the new value
112 * @return {@code true} if successful. False return indicates that
113 * the actual value was not bitwise equal to the expected value.
114 */
115 public final boolean compareAndSet(double expect, double update) {
116 return unsafe.compareAndSwapLong(this, valueOffset,
117 doubleToRawLongBits(expect),
118 doubleToRawLongBits(update));
119 }
120
121 /**
122 * Atomically sets the value to the given updated value
123 * if the current value is <a href="#bitEquals">bitwise equal</a>
124 * to the expected value.
125 *
126 * <p><a
127 * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
128 * May fail spuriously and does not provide ordering guarantees</a>,
129 * so is only rarely an appropriate alternative to {@code compareAndSet}.
130 *
131 * @param expect the expected value
132 * @param update the new value
133 * @return {@code true} if successful
134 */
135 public final boolean weakCompareAndSet(double expect, double update) {
136 return compareAndSet(expect, update);
137 }
138
139 /**
140 * Atomically adds the given value to the current value.
141 *
142 * @param delta the value to add
143 * @return the previous value
144 */
145 public final double getAndAdd(double delta) {
146 while (true) {
147 long current = value;
148 double currentVal = longBitsToDouble(current);
149 double nextVal = currentVal + delta;
150 long next = doubleToRawLongBits(nextVal);
151 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
152 return currentVal;
153 }
154 }
155
156 /**
157 * Atomically adds the given value to the current value.
158 *
159 * @param delta the value to add
160 * @return the updated value
161 */
162 public final double addAndGet(double delta) {
163 while (true) {
164 long current = value;
165 double currentVal = longBitsToDouble(current);
166 double nextVal = currentVal + delta;
167 long next = doubleToRawLongBits(nextVal);
168 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
169 return nextVal;
170 }
171 }
172
173 /**
174 * Returns the String representation of the current value.
175 * @return the String representation of the current value
176 */
177 public String toString() {
178 return Double.toString(get());
179 }
180
181 /**
182 * Returns the value of this {@code AtomicDouble} as an {@code int}
183 * after a narrowing primitive conversion.
184 */
185 public int intValue() {
186 return (int) get();
187 }
188
189 /**
190 * Returns the value of this {@code AtomicDouble} as a {@code long}
191 * after a narrowing primitive conversion.
192 */
193 public long longValue() {
194 return (long) get();
195 }
196
197 /**
198 * Returns the value of this {@code AtomicDouble} as a {@code float}
199 * after a narrowing primitive conversion.
200 */
201 public float floatValue() {
202 return (float) get();
203 }
204
205 /**
206 * Returns the value of this {@code AtomicDouble} as a {@code double}.
207 */
208 public double doubleValue() {
209 return get();
210 }
211
212 /**
213 * Saves the state to a stream (that is, serializes it).
214 *
215 * @param s the stream
216 * @throws java.io.IOException if an I/O error occurs
217 * @serialData The current value is emitted (a {@code double}).
218 */
219 private void writeObject(java.io.ObjectOutputStream s)
220 throws java.io.IOException {
221 s.defaultWriteObject();
222
223 s.writeDouble(get());
224 }
225
226 /**
227 * Reconstitutes the instance from a stream (that is, deserializes it).
228 * @param s the stream
229 * @throws ClassNotFoundException if the class of a serialized object
230 * could not be found
231 * @throws java.io.IOException if an I/O error occurs
232 */
233 private void readObject(java.io.ObjectInputStream s)
234 throws java.io.IOException, ClassNotFoundException {
235 s.defaultReadObject();
236
237 set(s.readDouble());
238 }
239
240 // Unsafe mechanics
241 private static final sun.misc.Unsafe unsafe = getUnsafe();
242 private static final long valueOffset;
243
244 static {
245 try {
246 valueOffset = unsafe.objectFieldOffset
247 (AtomicDouble.class.getDeclaredField("value"));
248 } catch (Exception ex) { throw new Error(ex); }
249 }
250
251 /**
252 * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
253 * Replace with a simple call to Unsafe.getUnsafe when integrating
254 * into a jdk.
255 *
256 * @return a sun.misc.Unsafe
257 */
258 private static sun.misc.Unsafe getUnsafe() {
259 try {
260 return sun.misc.Unsafe.getUnsafe();
261 } catch (SecurityException tryReflectionInstead) {}
262 try {
263 return java.security.AccessController.doPrivileged
264 (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
265 public sun.misc.Unsafe run() throws Exception {
266 Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
267 for (java.lang.reflect.Field f : k.getDeclaredFields()) {
268 f.setAccessible(true);
269 Object x = f.get(null);
270 if (k.isInstance(x))
271 return k.cast(x);
272 }
273 throw new NoSuchFieldError("the Unsafe");
274 }});
275 } catch (java.security.PrivilegedActionException e) {
276 throw new RuntimeException("Could not initialize intrinsics",
277 e.getCause());
278 }
279 }
280 }