ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.14
Committed: Wed Jan 9 02:51:37 2013 UTC (11 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.13: +17 -15 lines
Log Message:
more portable getUnsafe()

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 jsr166 1.10 * static boolean bitEquals(double x, double y) {
29 jsr166 1.2 * 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.8 private static final long serialVersionUID = -8405198993435143622L;
42 jsr166 1.1
43 jsr166 1.12 private transient volatile long value;
44 jsr166 1.1
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 jsr166 1.9 public AtomicDouble() {
58     // assert doubleToRawLongBits(0.0) == 0L;
59     }
60 jsr166 1.1
61     /**
62     * Gets the current value.
63     *
64     * @return the current value
65     */
66     public final double get() {
67     return longBitsToDouble(value);
68     }
69    
70     /**
71     * Sets to the given value.
72     *
73     * @param newValue the new value
74     */
75     public final void set(double newValue) {
76 jsr166 1.5 long next = doubleToRawLongBits(newValue);
77     value = next;
78 jsr166 1.1 }
79    
80     /**
81     * Eventually sets to the given value.
82     *
83     * @param newValue the new value
84     */
85     public final void lazySet(double newValue) {
86 jsr166 1.5 long next = doubleToRawLongBits(newValue);
87     unsafe.putOrderedLong(this, valueOffset, next);
88 jsr166 1.1 }
89    
90     /**
91     * Atomically sets to the given value and returns the old value.
92     *
93     * @param newValue the new value
94     * @return the previous value
95     */
96     public final double getAndSet(double newValue) {
97 jsr166 1.5 long next = doubleToRawLongBits(newValue);
98 jsr166 1.1 while (true) {
99 jsr166 1.5 long current = value;
100     if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
101     return longBitsToDouble(current);
102 jsr166 1.1 }
103     }
104    
105     /**
106     * Atomically sets the value to the given updated value
107 jsr166 1.5 * if the current value is <a href="#bitEquals">bitwise equal</a>
108     * to the expected value.
109 jsr166 1.1 *
110     * @param expect the expected value
111     * @param update the new value
112 jsr166 1.5 * @return {@code true} if successful. False return indicates that
113     * the actual value was not bitwise equal to the expected value.
114 jsr166 1.1 */
115     public final boolean compareAndSet(double expect, double update) {
116     return unsafe.compareAndSwapLong(this, valueOffset,
117     doubleToRawLongBits(expect),
118     doubleToRawLongBits(update));
119     }
120    
121     /**
122     * Atomically sets the value to the given updated value
123 jsr166 1.5 * if the current value is <a href="#bitEquals">bitwise equal</a>
124     * to the expected value.
125 jsr166 1.1 *
126 jsr166 1.9 * <p>May <a
127     * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
128     * fail spuriously</a>
129 jsr166 1.1 * and does not provide ordering guarantees, so is only rarely an
130     * appropriate alternative to {@code compareAndSet}.
131     *
132     * @param expect the expected value
133     * @param update the new value
134 jsr166 1.5 * @return {@code true} if successful
135 jsr166 1.1 */
136     public final boolean weakCompareAndSet(double expect, double update) {
137     return compareAndSet(expect, update);
138     }
139    
140     /**
141     * Atomically adds the given value to the current value.
142     *
143     * @param delta the value to add
144     * @return the previous value
145     */
146     public final double getAndAdd(double delta) {
147     while (true) {
148 jsr166 1.5 long current = value;
149     double currentVal = longBitsToDouble(current);
150     double nextVal = currentVal + delta;
151     long next = doubleToRawLongBits(nextVal);
152     if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
153     return currentVal;
154 jsr166 1.1 }
155     }
156    
157     /**
158     * Atomically adds the given value to the current value.
159     *
160     * @param delta the value to add
161     * @return the updated value
162     */
163     public final double addAndGet(double delta) {
164 jsr166 1.5 while (true) {
165     long current = value;
166     double currentVal = longBitsToDouble(current);
167     double nextVal = currentVal + delta;
168     long next = doubleToRawLongBits(nextVal);
169     if (unsafe.compareAndSwapLong(this, valueOffset, current, next))
170     return nextVal;
171 jsr166 1.1 }
172     }
173    
174     /**
175     * Returns the String representation of the current value.
176 jsr166 1.5 * @return the String representation of the current value
177 jsr166 1.1 */
178     public String toString() {
179     return Double.toString(get());
180     }
181    
182     /**
183     * Returns the value of this {@code AtomicDouble} as an {@code int}
184     * after a narrowing primitive conversion.
185     */
186     public int intValue() {
187 jsr166 1.9 return (int) get();
188 jsr166 1.1 }
189    
190     /**
191 jsr166 1.5 * Returns the value of this {@code AtomicDouble} as a {@code long}
192     * after a narrowing primitive conversion.
193 jsr166 1.1 */
194     public long longValue() {
195 jsr166 1.9 return (long) get();
196 jsr166 1.1 }
197    
198     /**
199     * Returns the value of this {@code AtomicDouble} as a {@code float}
200 jsr166 1.5 * after a narrowing primitive conversion.
201 jsr166 1.1 */
202     public float floatValue() {
203 jsr166 1.9 return (float) get();
204 jsr166 1.1 }
205    
206     /**
207 jsr166 1.5 * Returns the value of this {@code AtomicDouble} as a {@code double}.
208 jsr166 1.1 */
209     public double doubleValue() {
210     return get();
211     }
212    
213 jsr166 1.11 /**
214     * Saves the state to a stream (that is, serializes it).
215     *
216     * @serialData The current value is emitted (a {@code double}).
217     */
218     private void writeObject(java.io.ObjectOutputStream s)
219 jsr166 1.13 throws java.io.IOException {
220 jsr166 1.11 s.defaultWriteObject();
221    
222     s.writeDouble(get());
223     }
224    
225     /**
226     * Reconstitutes the instance from a stream (that is, deserializes it).
227     */
228     private void readObject(java.io.ObjectInputStream s)
229     throws java.io.IOException, ClassNotFoundException {
230     s.defaultReadObject();
231    
232     set(s.readDouble());
233     }
234    
235 jsr166 1.5 // Unsafe mechanics
236     private static final sun.misc.Unsafe unsafe = getUnsafe();
237     private static final long valueOffset;
238    
239     static {
240     try {
241     valueOffset = unsafe.objectFieldOffset
242     (AtomicDouble.class.getDeclaredField("value"));
243     } catch (Exception ex) { throw new Error(ex); }
244     }
245    
246 jsr166 1.3 /**
247     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
248     * Replace with a simple call to Unsafe.getUnsafe when integrating
249     * into a jdk.
250     *
251     * @return a sun.misc.Unsafe
252     */
253     private static sun.misc.Unsafe getUnsafe() {
254     try {
255     return sun.misc.Unsafe.getUnsafe();
256 jsr166 1.14 } catch (SecurityException tryReflectionInstead) {}
257     try {
258     return java.security.AccessController.doPrivileged
259     (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
260     public sun.misc.Unsafe run() throws Exception {
261     Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
262     for (java.lang.reflect.Field f : k.getDeclaredFields()) {
263     f.setAccessible(true);
264     Object x = f.get(null);
265     if (k.isInstance(x))
266     return k.cast(x);
267     }
268     throw new NoSuchFieldError("the Unsafe");
269     }});
270     } catch (java.security.PrivilegedActionException e) {
271     throw new RuntimeException("Could not initialize intrinsics",
272     e.getCause());
273 jsr166 1.3 }
274     }
275 jsr166 1.1 }