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

# 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     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 jsr166 1.2 * description of the properties of atomic variables. An {@code
16 jsr166 1.3 * AtomicDouble} is used in applications such as atomic accumulation,
17     * and cannot be used as a replacement for a {@link Double}. However,
18 jsr166 1.2 * this class does extend {@code Number} to allow uniform access by
19     * tools and utilities that deal with numerically-based classes.
20 jsr166 1.1 *
21 jsr166 1.2 * <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 jsr166 1.3 *
32 jsr166 1.1 * @author Doug Lea
33 jsr166 1.2 * @author Martin Buchholz
34 jsr166 1.1 */
35     public class AtomicDouble extends Number implements java.io.Serializable {
36 jsr166 1.3 static final long serialVersionUID = -8405198993435143622L;
37 jsr166 1.1
38     // setup to use Unsafe.compareAndSwapLong for updates
39 jsr166 1.3 private static final sun.misc.Unsafe unsafe = getUnsafe();
40 jsr166 1.1 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 jsr166 1.2 if (unsafe.compareAndSwapLong(this, valueOffset,
103     currentBits, newBits))
104 jsr166 1.1 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 jsr166 1.2 if (unsafe.compareAndSwapLong(this, valueOffset,
150     currentBits, nextBits))
151 jsr166 1.1 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 jsr166 1.3 /**
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 jsr166 1.1 }