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

# 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.7 * @see jsr166e.DoubleAdder
35     * @see jsr166e.DoubleMaxUpdater
36     *
37 jsr166 1.1 * @author Doug Lea
38 jsr166 1.2 * @author Martin Buchholz
39 jsr166 1.1 */
40     public class AtomicDouble extends Number implements java.io.Serializable {
41 jsr166 1.3 static final long serialVersionUID = -8405198993435143622L;
42 jsr166 1.1
43     private volatile long value;
44    
45     /**
46 jsr166 1.6 * Creates a new {@code AtomicDouble} with the given initial value.
47 jsr166 1.1 *
48     * @param initialValue the initial value
49     */
50     public AtomicDouble(double initialValue) {
51     value = doubleToRawLongBits(initialValue);
52     }
53    
54     /**
55 jsr166 1.6 * Creates a new {@code AtomicDouble} with initial value {@code 0.0}.
56 jsr166 1.1 */
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 jsr166 1.5 long next = doubleToRawLongBits(newValue);
75     value = next;
76 jsr166 1.1 }
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 jsr166 1.5 long next = doubleToRawLongBits(newValue);
85     unsafe.putOrderedLong(this, valueOffset, next);
86 jsr166 1.1 }
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 jsr166 1.5 long next = doubleToRawLongBits(newValue);
96 jsr166 1.1 while (true) {
97 jsr166 1.5 long current = value;
98     if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
99     return longBitsToDouble(current);
100 jsr166 1.1 }
101     }
102    
103     /**
104     * Atomically sets the value to the given updated value
105 jsr166 1.5 * if the current value is <a href="#bitEquals">bitwise equal</a>
106     * to the expected value.
107 jsr166 1.1 *
108     * @param expect the expected value
109     * @param update the new value
110 jsr166 1.5 * @return {@code true} if successful. False return indicates that
111     * the actual value was not bitwise equal to the expected value.
112 jsr166 1.1 */
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 jsr166 1.5 * if the current value is <a href="#bitEquals">bitwise equal</a>
122     * to the expected value.
123 jsr166 1.1 *
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 jsr166 1.5 * @return {@code true} if successful
131 jsr166 1.1 */
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 jsr166 1.5 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 jsr166 1.1 }
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 jsr166 1.5 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 jsr166 1.1 }
168     }
169    
170     /**
171     * Returns the String representation of the current value.
172 jsr166 1.5 * @return the String representation of the current value
173 jsr166 1.1 */
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 jsr166 1.5 * Returns the value of this {@code AtomicDouble} as a {@code long}
188     * after a narrowing primitive conversion.
189 jsr166 1.1 */
190     public long longValue() {
191     return (long)get();
192     }
193    
194     /**
195     * Returns the value of this {@code AtomicDouble} as a {@code float}
196 jsr166 1.5 * after a narrowing primitive conversion.
197 jsr166 1.1 */
198     public float floatValue() {
199     return (float)get();
200     }
201    
202     /**
203 jsr166 1.5 * Returns the value of this {@code AtomicDouble} as a {@code double}.
204 jsr166 1.1 */
205     public double doubleValue() {
206     return get();
207     }
208    
209 jsr166 1.5 // 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 jsr166 1.3 /**
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 jsr166 1.1 }