ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.4
Committed: Tue Aug 9 19:10:29 2011 UTC (12 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.3: +0 -26 lines
Log Message:
nuke VM_SUPPORTS_LONG_CAS - not needed

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 import static java.lang.Double.doubleToRawLongBits;
10 import static java.lang.Double.longBitsToDouble;
11
12 /**
13 * A {@code double} value that may be updated atomically. See the
14 * {@link java.util.concurrent.atomic} package specification for
15 * description of the properties of atomic variables. An {@code
16 * AtomicDouble} is used in applications such as atomic accumulation,
17 * and cannot be used as a replacement for a {@link Double}. However,
18 * this class does extend {@code Number} to allow uniform access by
19 * tools and utilities that deal with numerically-based classes.
20 *
21 * <p>This class differs from the primitive double {@code ==} operator
22 * and from {@link Double#equals} in that it uses purely bitwise
23 * equality in methods such as {@link #compareAndSet}, as if
24 * implemented by:
25 * <pre> {@code
26 * boolean bitEquals(double x, double y) {
27 * long xBits = Double.doubleToRawLongBits(x);
28 * long yBits = Double.doubleToRawLongBits(y);
29 * return xBits == yBits;
30 * }}</pre>
31 *
32 * @author Doug Lea
33 * @author Martin Buchholz
34 */
35 public class AtomicDouble extends Number implements java.io.Serializable {
36 static final long serialVersionUID = -8405198993435143622L;
37
38 // setup to use Unsafe.compareAndSwapLong for updates
39 private static final sun.misc.Unsafe unsafe = getUnsafe();
40 private static final long valueOffset;
41
42 static {
43 try {
44 valueOffset = unsafe.objectFieldOffset
45 (AtomicDouble.class.getDeclaredField("value"));
46 } catch (Exception ex) { throw new Error(ex); }
47 }
48
49 private volatile long value;
50
51 /**
52 * Creates a new AtomicDouble with the given initial value.
53 *
54 * @param initialValue the initial value
55 */
56 public AtomicDouble(double initialValue) {
57 value = doubleToRawLongBits(initialValue);
58 }
59
60 /**
61 * Creates a new AtomicDouble with initial value {@code 0.0}.
62 */
63 public AtomicDouble() { this(0.0); }
64
65 /**
66 * Gets the current value.
67 *
68 * @return the current value
69 */
70 public final double get() {
71 return longBitsToDouble(value);
72 }
73
74 /**
75 * Sets to the given value.
76 *
77 * @param newValue the new value
78 */
79 public final void set(double newValue) {
80 value = doubleToRawLongBits(newValue);
81 }
82
83 /**
84 * Eventually sets to the given value.
85 *
86 * @param newValue the new value
87 */
88 public final void lazySet(double newValue) {
89 unsafe.putOrderedLong(this, valueOffset, doubleToRawLongBits(newValue));
90 }
91
92 /**
93 * Atomically sets to the given value and returns the old value.
94 *
95 * @param newValue the new value
96 * @return the previous value
97 */
98 public final double getAndSet(double newValue) {
99 long newBits = doubleToRawLongBits(newValue);
100 while (true) {
101 long currentBits = value;
102 if (unsafe.compareAndSwapLong(this, valueOffset,
103 currentBits, newBits))
104 return longBitsToDouble(currentBits);
105 }
106 }
107
108 /**
109 * Atomically sets the value to the given updated value
110 * if the current value {@code ==} the expected value.
111 *
112 * @param expect the expected value
113 * @param update the new value
114 * @return true if successful. False return indicates that
115 * the actual value was not equal to the expected value.
116 */
117 public final boolean compareAndSet(double expect, double update) {
118 return unsafe.compareAndSwapLong(this, valueOffset,
119 doubleToRawLongBits(expect),
120 doubleToRawLongBits(update));
121 }
122
123 /**
124 * Atomically sets the value to the given updated value
125 * if the current value {@code ==} the expected value.
126 *
127 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
128 * and does not provide ordering guarantees, so is only rarely an
129 * appropriate alternative to {@code compareAndSet}.
130 *
131 * @param expect the expected value
132 * @param update the new value
133 * @return 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 currentBits = value;
148 long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
149 if (unsafe.compareAndSwapLong(this, valueOffset,
150 currentBits, nextBits))
151 return longBitsToDouble(currentBits);
152 }
153 }
154
155 /**
156 * Atomically adds the given value to the current value.
157 *
158 * @param delta the value to add
159 * @return the updated value
160 */
161 public final double addAndGet(double delta) {
162 for (;;) {
163 double current = get();
164 double next = current + delta;
165 if (compareAndSet(current, next))
166 return next;
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 /**
180 * Returns the value of this {@code AtomicDouble} as an {@code int}
181 * after a narrowing primitive conversion.
182 */
183 public int intValue() {
184 return (int)get();
185 }
186
187 /**
188 * Returns the value of this {@code AtomicDouble} as a {@code long}.
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 widening 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 * after a widening primitive conversion.
205 */
206 public double doubleValue() {
207 return get();
208 }
209
210 /**
211 * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
212 * Replace with a simple call to Unsafe.getUnsafe when integrating
213 * into a jdk.
214 *
215 * @return a sun.misc.Unsafe
216 */
217 private static sun.misc.Unsafe getUnsafe() {
218 try {
219 return sun.misc.Unsafe.getUnsafe();
220 } catch (SecurityException se) {
221 try {
222 return java.security.AccessController.doPrivileged
223 (new java.security
224 .PrivilegedExceptionAction<sun.misc.Unsafe>() {
225 public sun.misc.Unsafe run() throws Exception {
226 java.lang.reflect.Field f = sun.misc
227 .Unsafe.class.getDeclaredField("theUnsafe");
228 f.setAccessible(true);
229 return (sun.misc.Unsafe) f.get(null);
230 }});
231 } catch (java.security.PrivilegedActionException e) {
232 throw new RuntimeException("Could not initialize intrinsics",
233 e.getCause());
234 }
235 }
236 }
237
238 }