ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.7
Committed: Wed Oct 19 23:01:30 2011 UTC (12 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.6: +3 -0 lines
Log Message:
add @see to scalable updaters

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 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() { this(0.0); }
58
59 /**
60 * Gets the current value.
61 *
62 * @return the current value
63 */
64 public final double get() {
65 return longBitsToDouble(value);
66 }
67
68 /**
69 * Sets to the given value.
70 *
71 * @param newValue the new value
72 */
73 public final void set(double newValue) {
74 long next = doubleToRawLongBits(newValue);
75 value = next;
76 }
77
78 /**
79 * Eventually sets to the given value.
80 *
81 * @param newValue the new value
82 */
83 public final void lazySet(double newValue) {
84 long next = doubleToRawLongBits(newValue);
85 unsafe.putOrderedLong(this, valueOffset, next);
86 }
87
88 /**
89 * Atomically sets to the given value and returns the old value.
90 *
91 * @param newValue the new value
92 * @return the previous value
93 */
94 public final double getAndSet(double newValue) {
95 long next = doubleToRawLongBits(newValue);
96 while (true) {
97 long current = value;
98 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
99 return longBitsToDouble(current);
100 }
101 }
102
103 /**
104 * Atomically sets the value to the given updated value
105 * if the current value is <a href="#bitEquals">bitwise equal</a>
106 * to the expected value.
107 *
108 * @param expect the expected value
109 * @param update the new value
110 * @return {@code true} if successful. False return indicates that
111 * the actual value was not bitwise equal to the expected value.
112 */
113 public final boolean compareAndSet(double expect, double update) {
114 return unsafe.compareAndSwapLong(this, valueOffset,
115 doubleToRawLongBits(expect),
116 doubleToRawLongBits(update));
117 }
118
119 /**
120 * Atomically sets the value to the given updated value
121 * if the current value is <a href="#bitEquals">bitwise equal</a>
122 * to the expected value.
123 *
124 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
125 * and does not provide ordering guarantees, so is only rarely an
126 * appropriate alternative to {@code compareAndSet}.
127 *
128 * @param expect the expected value
129 * @param update the new value
130 * @return {@code true} if successful
131 */
132 public final boolean weakCompareAndSet(double expect, double update) {
133 return compareAndSet(expect, update);
134 }
135
136 /**
137 * Atomically adds the given value to the current value.
138 *
139 * @param delta the value to add
140 * @return the previous value
141 */
142 public final double getAndAdd(double delta) {
143 while (true) {
144 long current = value;
145 double currentVal = longBitsToDouble(current);
146 double nextVal = currentVal + delta;
147 long next = doubleToRawLongBits(nextVal);
148 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
149 return currentVal;
150 }
151 }
152
153 /**
154 * Atomically adds the given value to the current value.
155 *
156 * @param delta the value to add
157 * @return the updated value
158 */
159 public final double addAndGet(double delta) {
160 while (true) {
161 long current = value;
162 double currentVal = longBitsToDouble(current);
163 double nextVal = currentVal + delta;
164 long next = doubleToRawLongBits(nextVal);
165 if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
166 return nextVal;
167 }
168 }
169
170 /**
171 * Returns the String representation of the current value.
172 * @return the String representation of the current value
173 */
174 public String toString() {
175 return Double.toString(get());
176 }
177
178 /**
179 * Returns the value of this {@code AtomicDouble} as an {@code int}
180 * after a narrowing primitive conversion.
181 */
182 public int intValue() {
183 return (int)get();
184 }
185
186 /**
187 * Returns the value of this {@code AtomicDouble} as a {@code long}
188 * after a narrowing primitive conversion.
189 */
190 public long longValue() {
191 return (long)get();
192 }
193
194 /**
195 * Returns the value of this {@code AtomicDouble} as a {@code float}
196 * after a narrowing primitive conversion.
197 */
198 public float floatValue() {
199 return (float)get();
200 }
201
202 /**
203 * Returns the value of this {@code AtomicDouble} as a {@code double}.
204 */
205 public double doubleValue() {
206 return get();
207 }
208
209 // Unsafe mechanics
210 private static final sun.misc.Unsafe unsafe = getUnsafe();
211 private static final long valueOffset;
212
213 static {
214 try {
215 valueOffset = unsafe.objectFieldOffset
216 (AtomicDouble.class.getDeclaredField("value"));
217 } catch (Exception ex) { throw new Error(ex); }
218 }
219
220 /**
221 * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
222 * Replace with a simple call to Unsafe.getUnsafe when integrating
223 * into a jdk.
224 *
225 * @return a sun.misc.Unsafe
226 */
227 private static sun.misc.Unsafe getUnsafe() {
228 try {
229 return sun.misc.Unsafe.getUnsafe();
230 } catch (SecurityException se) {
231 try {
232 return java.security.AccessController.doPrivileged
233 (new java.security
234 .PrivilegedExceptionAction<sun.misc.Unsafe>() {
235 public sun.misc.Unsafe run() throws Exception {
236 java.lang.reflect.Field f = sun.misc
237 .Unsafe.class.getDeclaredField("theUnsafe");
238 f.setAccessible(true);
239 return (sun.misc.Unsafe) f.get(null);
240 }});
241 } catch (java.security.PrivilegedActionException e) {
242 throw new RuntimeException("Could not initialize intrinsics",
243 e.getCause());
244 }
245 }
246 }
247 }