| AtomicLong.java |
1 /*
2 * %W% %E%
3 *
4 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6 */
7
8 package java.util.concurrent.atomic;
9 import sun.misc.Unsafe;
10
11 /**
12 * A {@code long} value that may be updated atomically. See the
13 * {@link java.util.concurrent.atomic} package specification for
14 * description of the properties of atomic variables. An
15 * {@code AtomicLong} is used in applications such as atomically
16 * incremented sequence numbers, and cannot be used as a replacement
17 * for a {@link java.lang.Long}. However, this class does extend
18 * {@code Number} to allow uniform access by tools and utilities that
19 * deal with numerically-based classes.
20 *
21 * @since 1.5
22 * @author Doug Lea
23 */
24 public class AtomicLong extends Number implements java.io.Serializable {
25 private static final long serialVersionUID = 1927816293512124184L;
26
27 // setup to use Unsafe.compareAndSwapLong for updates
28 private static final Unsafe unsafe = Unsafe.getUnsafe();
29 private static final long valueOffset;
30
31 /**
32 * Records whether the underlying JVM supports lockless
33 * CompareAndSet for longs. While the unsafe.CompareAndSetLong
34 * method works in either case, some constructions should be
35 * handled at Java level to avoid locking user-visible locks.
36 */
37 static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
38
39 /**
40 * Returns whether underlying JVM supports lockless CompareAndSet
41 * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
42 */
43 private static native boolean VMSupportsCS8();
44
45 static {
46 try {
47 valueOffset = unsafe.objectFieldOffset
48 (AtomicLong.class.getDeclaredField("value"));
49 } catch (Exception ex) { throw new Error(ex); }
50 }
51
52 private volatile long value;
53
54 /**
55 * Creates a new AtomicLong with the given initial value.
56 *
57 * @param initialValue the initial value
58 */
59 public AtomicLong(long initialValue) {
60 value = initialValue;
61 }
62
63 /**
64 * Creates a new AtomicLong with initial value {@code 0}.
65 */
66 public AtomicLong() {
67 }
68
69 /**
70 * Gets the current value.
71 *
72 * @return the current value
73 */
74 public final long get() {
75 return value;
76 }
77
78 /**
79 * Sets to the given value.
80 *
81 * @param newValue the new value
82 */
83 public final void set(long newValue) {
84 value = 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(long newValue) {
94 unsafe.putOrderedLong(this, valueOffset, 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 long getAndSet(long newValue) {
104 while (true) {
105 long current = get();
106 if (compareAndSet(current, newValue))
107 return current;
108 }
109 }
110
111 /**
112 * Atomically sets the value to the given updated value
113 * if the current value {@code ==} the expected value.
114 *
115 * @param expect the expected value
116 * @param update the new value
117 * @return true if successful. False return indicates that
118 * the actual value was not equal to the expected value.
119 */
120 public final boolean compareAndSet(long expect, long update) {
121 return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
122 }
123
124 /**
125 * Atomically sets the value to the given updated value
126 * if the current value {@code ==} the expected value.
127 *
128 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
129 * 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 * @return true if successful.
135 */
136 public final boolean weakCompareAndSet(long expect, long update) {
137 return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
138 }
139
140 /**
141 * Atomically increments by one the current value.
142 *
143 * @return the previous value
144 */
145 public final long getAndIncrement() {
146 while (true) {
147 long current = get();
148 long next = current + 1;
149 if (compareAndSet(current, next))
150 return current;
151 }
152 }
153
154 /**
155 * Atomically decrements by one the current value.
156 *
157 * @return the previous value
158 */
159 public final long getAndDecrement() {
160 while (true) {
161 long current = get();
162 long next = current - 1;
163 if (compareAndSet(current, next))
164 return current;
165 }
166 }
167
168 /**
169 * Atomically adds the given value to the current value.
170 *
171 * @param delta the value to add
172 * @return the previous value
173 */
174 public final long getAndAdd(long delta) {
175 while (true) {
176 long current = get();
177 long next = current + delta;
178 if (compareAndSet(current, next))
179 return current;
180 }
181 }
182
183 /**
184 * Atomically increments by one the current value.
185 *
186 * @return the updated value
187 */
188 public final long incrementAndGet() {
189 for (;;) {
190 long current = get();
191 long next = current + 1;
192 if (compareAndSet(current, next))
193 return next;
194 }
195 }
196
197 /**
198 * Atomically decrements by one the current value.
199 *
200 * @return the updated value
201 */
202 public final long decrementAndGet() {
203 for (;;) {
204 long current = get();
205 long next = current - 1;
206 if (compareAndSet(current, next))
207 return next;
208 }
209 }
210
211 /**
212 * Atomically adds the given value to the current value.
213 *
214 * @param delta the value to add
215 * @return the updated value
216 */
217 public final long addAndGet(long delta) {
218 for (;;) {
219 long current = get();
220 long next = current + delta;
221 if (compareAndSet(current, next))
222 return next;
223 }
224 }
225
226 /**
227 * Returns the String representation of the current value.
228 * @return the String representation of the current value.
229 */
230 public String toString() {
231 return Long.toString(get());
232 }
233
234
235 public int intValue() {
236 return (int)get();
237 }
238
239 public long longValue() {
240 return (long)get();
241 }
242
243 public float floatValue() {
244 return (float)get();
245 }
246
247 public double doubleValue() {
248 return (double)get();
249 }
250
251 }
252