ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.5
Committed: Wed Aug 10 01:29:45 2011 UTC (12 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.4: +50 -43 lines
Log Message:
seems production ready

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