ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.6
Committed: Wed Aug 10 04:35:04 2011 UTC (12 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.5: +2 -3 lines
Log Message:
minor doc updates

File Contents

# User Rev Content
1 jsr166 1.1 /*
2 jsr166 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 jsr166 1.1 * http://creativecommons.org/publicdomain/zero/1.0/
6     */
7    
8     package jsr166e.extra;
9 jsr166 1.5
10 jsr166 1.1 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 jsr166 1.2 * description of the properties of atomic variables. An {@code
17 jsr166 1.3 * AtomicDouble} is used in applications such as atomic accumulation,
18     * and cannot be used as a replacement for a {@link Double}. However,
19 jsr166 1.2 * this class does extend {@code Number} to allow uniform access by
20     * tools and utilities that deal with numerically-based classes.
21 jsr166 1.1 *
22 jsr166 1.5 * <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 jsr166 1.2 * <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 jsr166 1.3 *
34 jsr166 1.1 * @author Doug Lea
35 jsr166 1.2 * @author Martin Buchholz
36 jsr166 1.1 */
37     public class AtomicDouble extends Number implements java.io.Serializable {
38 jsr166 1.3 static final long serialVersionUID = -8405198993435143622L;
39 jsr166 1.1
40     private volatile long value;
41    
42     /**
43 jsr166 1.6 * Creates a new {@code AtomicDouble} with the given initial value.
44 jsr166 1.1 *
45     * @param initialValue the initial value
46     */
47     public AtomicDouble(double initialValue) {
48     value = doubleToRawLongBits(initialValue);
49     }
50    
51     /**
52 jsr166 1.6 * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
53 jsr166 1.1 */
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 jsr166 1.5 long next = doubleToRawLongBits(newValue);
72     value = next;
73 jsr166 1.1 }
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 jsr166 1.5 long next = doubleToRawLongBits(newValue);
82     unsafe.putOrderedLong(this, valueOffset, next);
83 jsr166 1.1 }
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 jsr166 1.5 long next = doubleToRawLongBits(newValue);
93 jsr166 1.1 while (true) {
94 jsr166 1.5 long current = value;
95     if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
96     return longBitsToDouble(current);
97 jsr166 1.1 }
98     }
99    
100     /**
101     * Atomically sets the value to the given updated value
102 jsr166 1.5 * if the current value is <a href="#bitEquals">bitwise equal</a>
103     * to the expected value.
104 jsr166 1.1 *
105     * @param expect the expected value
106     * @param update the new value
107 jsr166 1.5 * @return {@code true} if successful. False return indicates that
108     * the actual value was not bitwise equal to the expected value.
109 jsr166 1.1 */
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 jsr166 1.5 * if the current value is <a href="#bitEquals">bitwise equal</a>
119     * to the expected value.
120 jsr166 1.1 *
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 jsr166 1.5 * @return {@code true} if successful
128 jsr166 1.1 */
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 jsr166 1.5 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 jsr166 1.1 }
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 jsr166 1.5 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 jsr166 1.1 }
165     }
166    
167     /**
168     * Returns the String representation of the current value.
169 jsr166 1.5 * @return the String representation of the current value
170 jsr166 1.1 */
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 jsr166 1.5 * Returns the value of this {@code AtomicDouble} as a {@code long}
185     * after a narrowing primitive conversion.
186 jsr166 1.1 */
187     public long longValue() {
188     return (long)get();
189     }
190    
191     /**
192     * Returns the value of this {@code AtomicDouble} as a {@code float}
193 jsr166 1.5 * after a narrowing primitive conversion.
194 jsr166 1.1 */
195     public float floatValue() {
196     return (float)get();
197     }
198    
199     /**
200 jsr166 1.5 * Returns the value of this {@code AtomicDouble} as a {@code double}.
201 jsr166 1.1 */
202     public double doubleValue() {
203     return get();
204     }
205    
206 jsr166 1.5 // 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 jsr166 1.3 /**
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 jsr166 1.1 }