ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.9
Committed: Thu Oct 20 16:33:25 2011 UTC (12 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.8: +9 -5 lines
Log Message:
incorporate feedback from guava reviewers; migrate to slightly more guava-compatible coding style

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><a name="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 * 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 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>May <a
127 * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
128 * fail spuriously</a>
129 * and does not provide ordering guarantees, so is only rarely an
130 * appropriate alternative to {@code compareAndSet}.
131 *
132 * @param expect the expected value
133 * @param update the new value
134 * @return {@code true} if successful
135 */
136 public final boolean weakCompareAndSet(double expect, double update) {
137 return compareAndSet(expect, update);
138 }
139
140 /**
141 * Atomically adds the given value to the current value.
142 *
143 * @param delta the value to add
144 * @return the previous value
145 */
146 public final double getAndAdd(double delta) {
147 while (true) {
148 long current = value;
149 double currentVal = longBitsToDouble(current);
150 double nextVal = currentVal + delta;
151 long next = doubleToRawLongBits(nextVal);
152 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
153 return currentVal;
154 }
155 }
156
157 /**
158 * Atomically adds the given value to the current value.
159 *
160 * @param delta the value to add
161 * @return the updated value
162 */
163 public final double addAndGet(double delta) {
164 while (true) {
165 long current = value;
166 double currentVal = longBitsToDouble(current);
167 double nextVal = currentVal + delta;
168 long next = doubleToRawLongBits(nextVal);
169 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
170 return nextVal;
171 }
172 }
173
174 /**
175 * Returns the String representation of the current value.
176 * @return the String representation of the current value
177 */
178 public String toString() {
179 return Double.toString(get());
180 }
181
182 /**
183 * Returns the value of this {@code AtomicDouble} as an {@code int}
184 * after a narrowing primitive conversion.
185 */
186 public int intValue() {
187 return (int) get();
188 }
189
190 /**
191 * Returns the value of this {@code AtomicDouble} as a {@code long}
192 * after a narrowing primitive conversion.
193 */
194 public long longValue() {
195 return (long) get();
196 }
197
198 /**
199 * Returns the value of this {@code AtomicDouble} as a {@code float}
200 * after a narrowing primitive conversion.
201 */
202 public float floatValue() {
203 return (float) get();
204 }
205
206 /**
207 * Returns the value of this {@code AtomicDouble} as a {@code double}.
208 */
209 public double doubleValue() {
210 return get();
211 }
212
213 // Unsafe mechanics
214 private static final sun.misc.Unsafe unsafe = getUnsafe();
215 private static final long valueOffset;
216
217 static {
218 try {
219 valueOffset = unsafe.objectFieldOffset
220 (AtomicDouble.class.getDeclaredField("value"));
221 } catch (Exception ex) { throw new Error(ex); }
222 }
223
224 /**
225 * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
226 * Replace with a simple call to Unsafe.getUnsafe when integrating
227 * into a jdk.
228 *
229 * @return a sun.misc.Unsafe
230 */
231 private static sun.misc.Unsafe getUnsafe() {
232 try {
233 return sun.misc.Unsafe.getUnsafe();
234 } catch (SecurityException se) {
235 try {
236 return java.security.AccessController.doPrivileged
237 (new java.security
238 .PrivilegedExceptionAction<sun.misc.Unsafe>() {
239 public sun.misc.Unsafe run() throws Exception {
240 java.lang.reflect.Field f = sun.misc
241 .Unsafe.class.getDeclaredField("theUnsafe");
242 f.setAccessible(true);
243 return (sun.misc.Unsafe) f.get(null);
244 }});
245 } catch (java.security.PrivilegedActionException e) {
246 throw new RuntimeException("Could not initialize intrinsics",
247 e.getCause());
248 }
249 }
250 }
251 }