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

# Content
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 }