ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/AtomicDouble.java
Revision: 1.1
Committed: Tue Aug 9 04:05:25 2011 UTC (12 years, 10 months ago) by jsr166
Branch: MAIN
Log Message:
release early, release often

File Contents

# User Rev Content
1 jsr166 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/publicdomain/zero/1.0/
5     */
6    
7     package jsr166e.extra;
8     import static java.lang.Double.doubleToRawLongBits;
9     import static java.lang.Double.longBitsToDouble;
10     import sun.misc.Unsafe;
11    
12     /**
13     * A {@code double} value that may be updated atomically. See the
14     * {@link java.util.concurrent.atomic} package specification for
15     * description of the properties of atomic variables. An
16     * {@code AtomicDouble} is used in applications such as atomically
17     * incremented sequence numbers, and cannot be used as a replacement
18     * for a {@link java.lang.Double}. However, this class does extend
19     * {@code Number} to allow uniform access by tools and utilities that
20     * deal with numerically-based classes.
21     *
22     * @since 1.5
23     * @author Doug Lea
24     */
25     public class AtomicDouble extends Number implements java.io.Serializable {
26     private static final long serialVersionUID = 1927816293512124184L;
27    
28     // setup to use Unsafe.compareAndSwapLong for updates
29     private static final Unsafe unsafe = Unsafe.getUnsafe();
30     private static final long valueOffset;
31    
32     /**
33     * Records whether the underlying JVM supports lockless
34     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
35     * method works in either case, some constructions should be
36     * handled at Java level to avoid locking user-visible locks.
37     */
38     static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
39    
40     /**
41     * Returns whether underlying JVM supports lockless CompareAndSet
42     * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
43     */
44     private static native boolean VMSupportsCS8();
45    
46     static {
47     try {
48     valueOffset = unsafe.objectFieldOffset
49     (AtomicDouble.class.getDeclaredField("value"));
50     } catch (Exception ex) { throw new Error(ex); }
51     }
52    
53     private volatile long value;
54    
55     /**
56     * Creates a new AtomicDouble with the given initial value.
57     *
58     * @param initialValue the initial value
59     */
60     public AtomicDouble(double initialValue) {
61     value = doubleToRawLongBits(initialValue);
62     }
63    
64     /**
65     * Creates a new AtomicDouble with initial value {@code 0.0}.
66     */
67     public AtomicDouble() { this(0.0); }
68    
69     /**
70     * Gets the current value.
71     *
72     * @return the current value
73     */
74     public final double get() {
75     return longBitsToDouble(value);
76     }
77    
78     /**
79     * Sets to the given value.
80     *
81     * @param newValue the new value
82     */
83     public final void set(double newValue) {
84     value = doubleToRawLongBits(newValue);
85     }
86    
87     /**
88     * Eventually sets to the given value.
89     *
90     * @param newValue the new value
91     * @since 1.6
92     */
93     public final void lazySet(double newValue) {
94     unsafe.putOrderedLong(this, valueOffset, doubleToRawLongBits(newValue));
95     }
96    
97     /**
98     * Atomically sets to the given value and returns the old value.
99     *
100     * @param newValue the new value
101     * @return the previous value
102     */
103     public final double getAndSet(double newValue) {
104     long newBits = doubleToRawLongBits(newValue);
105     while (true) {
106     long currentBits = value;
107     if (compareAndSet(currentBits, newBits))
108     return longBitsToDouble(currentBits);
109     }
110     }
111    
112     /**
113     * Atomically sets the value to the given updated value
114     * if the current value {@code ==} the expected value.
115     *
116     * @param expect the expected value
117     * @param update the new value
118     * @return true if successful. False return indicates that
119     * the actual value was not equal to the expected value.
120     */
121     public final boolean compareAndSet(double expect, double update) {
122     return unsafe.compareAndSwapLong(this, valueOffset,
123     doubleToRawLongBits(expect),
124     doubleToRawLongBits(update));
125     }
126    
127     /**
128     * Atomically sets the value to the given updated value
129     * if the current value {@code ==} the expected value.
130     *
131     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
132     * and does not provide ordering guarantees, so is only rarely an
133     * appropriate alternative to {@code compareAndSet}.
134     *
135     * @param expect the expected value
136     * @param update the new value
137     * @return true if successful.
138     */
139     public final boolean weakCompareAndSet(double expect, double update) {
140     return compareAndSet(expect, update);
141     }
142    
143     /**
144     * Atomically adds the given value to the current value.
145     *
146     * @param delta the value to add
147     * @return the previous value
148     */
149     public final double getAndAdd(double delta) {
150     while (true) {
151     long currentBits = value;
152     long nextBits = doubleToRawLongBits(longBitsToDouble(currentBits) + delta);
153     if (compareAndSet(currentBits, nextBits))
154     return longBitsToDouble(currentBits);
155     }
156     }
157    
158     /**
159     * Atomically adds the given value to the current value.
160     *
161     * @param delta the value to add
162     * @return the updated value
163     */
164     public final double addAndGet(double delta) {
165     for (;;) {
166     double current = get();
167     double next = current + delta;
168     if (compareAndSet(current, next))
169     return next;
170     }
171     }
172    
173     /**
174     * Returns the String representation of the current value.
175     * @return the String representation of the current value.
176     */
177     public String toString() {
178     return Double.toString(get());
179     }
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     return (int)get();
188     }
189    
190     /**
191     * Returns the value of this {@code AtomicDouble} as a {@code long}.
192     */
193     public long longValue() {
194     return (long)get();
195     }
196    
197     /**
198     * Returns the value of this {@code AtomicDouble} as a {@code float}
199     * after a widening primitive conversion.
200     */
201     public float floatValue() {
202     return (float)get();
203     }
204    
205     /**
206     * Returns the value of this {@code AtomicDouble} as a {@code double}
207     * after a widening primitive conversion.
208     */
209     public double doubleValue() {
210     return get();
211     }
212    
213     }