ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.2
Committed: Tue Aug 9 07:44:08 2011 UTC (12 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.1: +33 -11 lines
Log Message:
mostly works

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     import sun.misc.Unsafe;
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     * AtomicDouble} is used in applications such as atomic summation, and
18     * 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 jsr166 1.1 *
22 jsr166 1.2 * <p>This class differs from the primitive double {@code ==} operator
23     * and from {@link Double#equals} in that it uses purely bitwise
24     * equality in methods such as {@link #compareAndSet}, as if
25     * implemented by:
26     * <pre> {@code
27     * boolean bitEquals(double x, double y) {
28     * long xBits = Double.doubleToRawLongBits(x);
29     * long yBits = Double.doubleToRawLongBits(y);
30     * return xBits == yBits;
31     * }}</pre>
32     *
33 jsr166 1.1 * @since 1.5
34     * @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     private static final long serialVersionUID = 1927816293512124184L;
39    
40     // setup to use Unsafe.compareAndSwapLong for updates
41     private static final Unsafe unsafe = Unsafe.getUnsafe();
42     private static final long valueOffset;
43    
44     /**
45     * Records whether the underlying JVM supports lockless
46     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
47     * method works in either case, some constructions should be
48     * handled at Java level to avoid locking user-visible locks.
49     */
50     static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
51    
52     /**
53     * Returns whether underlying JVM supports lockless CompareAndSet
54     * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
55     */
56 jsr166 1.2 private static boolean VMSupportsCS8() {
57     try {
58     Class<?> klazz = java.util.concurrent.atomic.AtomicLong.class;
59     java.lang.reflect.Method m =
60     klazz.getDeclaredMethod("VMSupportsCS8", new Class<?>[0]);
61     m.setAccessible(true);
62     return (Boolean) m.invoke(new Class<?>[0]);
63     } catch (Throwable t) { throw new Error(t); }
64     }
65 jsr166 1.1
66     static {
67     try {
68     valueOffset = unsafe.objectFieldOffset
69     (AtomicDouble.class.getDeclaredField("value"));
70     } catch (Exception ex) { throw new Error(ex); }
71     }
72    
73     private volatile long value;
74    
75     /**
76     * Creates a new AtomicDouble with the given initial value.
77     *
78     * @param initialValue the initial value
79     */
80     public AtomicDouble(double initialValue) {
81     value = doubleToRawLongBits(initialValue);
82     }
83    
84     /**
85     * Creates a new AtomicDouble with initial value {@code 0.0}.
86     */
87     public AtomicDouble() { this(0.0); }
88    
89     /**
90     * Gets the current value.
91     *
92     * @return the current value
93     */
94     public final double get() {
95     return longBitsToDouble(value);
96     }
97    
98     /**
99     * Sets to the given value.
100     *
101     * @param newValue the new value
102     */
103     public final void set(double newValue) {
104     value = doubleToRawLongBits(newValue);
105     }
106    
107     /**
108     * Eventually sets to the given value.
109     *
110     * @param newValue the new value
111     * @since 1.6
112     */
113     public final void lazySet(double newValue) {
114     unsafe.putOrderedLong(this, valueOffset, doubleToRawLongBits(newValue));
115     }
116    
117     /**
118     * Atomically sets to the given value and returns the old value.
119     *
120     * @param newValue the new value
121     * @return the previous value
122     */
123     public final double getAndSet(double newValue) {
124     long newBits = doubleToRawLongBits(newValue);
125     while (true) {
126     long currentBits = value;
127 jsr166 1.2 if (unsafe.compareAndSwapLong(this, valueOffset,
128     currentBits, newBits))
129 jsr166 1.1 return longBitsToDouble(currentBits);
130     }
131     }
132    
133     /**
134     * Atomically sets the value to the given updated value
135     * if the current value {@code ==} the expected value.
136     *
137     * @param expect the expected value
138     * @param update the new value
139     * @return true if successful. False return indicates that
140     * the actual value was not equal to the expected value.
141     */
142     public final boolean compareAndSet(double expect, double update) {
143     return unsafe.compareAndSwapLong(this, valueOffset,
144     doubleToRawLongBits(expect),
145     doubleToRawLongBits(update));
146     }
147    
148     /**
149     * Atomically sets the value to the given updated value
150     * if the current value {@code ==} the expected value.
151     *
152     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
153     * and does not provide ordering guarantees, so is only rarely an
154     * appropriate alternative to {@code compareAndSet}.
155     *
156     * @param expect the expected value
157     * @param update the new value
158     * @return true if successful.
159     */
160     public final boolean weakCompareAndSet(double expect, double update) {
161     return compareAndSet(expect, update);
162     }
163    
164     /**
165     * Atomically adds the given value to the current value.
166     *
167     * @param delta the value to add
168     * @return the previous value
169     */
170     public final double getAndAdd(double delta) {
171     while (true) {
172     long currentBits = value;
173     long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
174 jsr166 1.2 if (unsafe.compareAndSwapLong(this, valueOffset,
175     currentBits, nextBits))
176 jsr166 1.1 return longBitsToDouble(currentBits);
177     }
178     }
179    
180     /**
181     * Atomically adds the given value to the current value.
182     *
183     * @param delta the value to add
184     * @return the updated value
185     */
186     public final double addAndGet(double delta) {
187     for (;;) {
188     double current = get();
189     double next = current + delta;
190     if (compareAndSet(current, next))
191     return next;
192     }
193     }
194    
195     /**
196     * Returns the String representation of the current value.
197     * @return the String representation of the current value.
198     */
199     public String toString() {
200     return Double.toString(get());
201     }
202    
203    
204     /**
205     * Returns the value of this {@code AtomicDouble} as an {@code int}
206     * after a narrowing primitive conversion.
207     */
208     public int intValue() {
209     return (int)get();
210     }
211    
212     /**
213     * Returns the value of this {@code AtomicDouble} as a {@code long}.
214     */
215     public long longValue() {
216     return (long)get();
217     }
218    
219     /**
220     * Returns the value of this {@code AtomicDouble} as a {@code float}
221     * after a widening primitive conversion.
222     */
223     public float floatValue() {
224     return (float)get();
225     }
226    
227     /**
228     * Returns the value of this {@code AtomicDouble} as a {@code double}
229     * after a widening primitive conversion.
230     */
231     public double doubleValue() {
232     return get();
233     }
234    
235     }