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 java.util.concurrent.atomic;
8 
9 import java.util.function.LongBinaryOperator;
10 import java.util.function.LongUnaryOperator;
11 
12 /**
13  * A {@code long} 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 AtomicLong} is used in applications such as atomically
17  * incremented sequence numbers, and cannot be used as a replacement
18  * for a {@link java.lang.Long}. 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 AtomicLong extends Number implements java.io.Serializable {
26     private static final long serialVersionUID = 1927816293512124184L;
27 
28     private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
29     private static final long VALUE;
30 
31     /**
32      * Records whether the underlying JVM supports lockless
33      * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
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      */
VMSupportsCS8()43     private static native boolean VMSupportsCS8();
44 
45     static {
46         try {
47             VALUE = U.objectFieldOffset
48                 (AtomicLong.class.getDeclaredField("value"));
49         } catch (ReflectiveOperationException e) {
50             throw new Error(e);
51         }
52     }
53 
54     private volatile long value;
55 
56     /**
57      * Creates a new AtomicLong with the given initial value.
58      *
59      * @param initialValue the initial value
60      */
AtomicLong(long initialValue)61     public AtomicLong(long initialValue) {
62         value = initialValue;
63     }
64 
65     /**
66      * Creates a new AtomicLong with initial value {@code 0}.
67      */
AtomicLong()68     public AtomicLong() {
69     }
70 
71     /**
72      * Gets the current value.
73      *
74      * @return the current value
75      */
get()76     public final long get() {
77         return value;
78     }
79 
80     /**
81      * Sets to the given value.
82      *
83      * @param newValue the new value
84      */
set(long newValue)85     public final void set(long newValue) {
86         // Use putLongVolatile instead of ordinary volatile store when
87         // using compareAndSwapLong, for sake of some 32bit systems.
88         U.putLongVolatile(this, VALUE, newValue);
89     }
90 
91     /**
92      * Eventually sets to the given value.
93      *
94      * @param newValue the new value
95      * @since 1.6
96      */
lazySet(long newValue)97     public final void lazySet(long newValue) {
98         U.putOrderedLong(this, VALUE, newValue);
99     }
100 
101     /**
102      * Atomically sets to the given value and returns the old value.
103      *
104      * @param newValue the new value
105      * @return the previous value
106      */
getAndSet(long newValue)107     public final long getAndSet(long newValue) {
108         return U.getAndSetLong(this, VALUE, newValue);
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 {@code true} if successful. False return indicates that
118      * the actual value was not equal to the expected value.
119      */
compareAndSet(long expect, long update)120     public final boolean compareAndSet(long expect, long update) {
121         return U.compareAndSwapLong(this, VALUE, 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><a href="package-summary.html#weakCompareAndSet">May fail
129      * spuriously and does not provide ordering guarantees</a>, so is
130      * only rarely an appropriate alternative to {@code compareAndSet}.
131      *
132      * @param expect the expected value
133      * @param update the new value
134      * @return {@code true} if successful
135      */
weakCompareAndSet(long expect, long update)136     public final boolean weakCompareAndSet(long expect, long update) {
137         return U.compareAndSwapLong(this, VALUE, expect, update);
138     }
139 
140     /**
141      * Atomically increments by one the current value.
142      *
143      * @return the previous value
144      */
getAndIncrement()145     public final long getAndIncrement() {
146         return U.getAndAddLong(this, VALUE, 1L);
147     }
148 
149     /**
150      * Atomically decrements by one the current value.
151      *
152      * @return the previous value
153      */
getAndDecrement()154     public final long getAndDecrement() {
155         return U.getAndAddLong(this, VALUE, -1L);
156     }
157 
158     /**
159      * Atomically adds the given value to the current value.
160      *
161      * @param delta the value to add
162      * @return the previous value
163      */
getAndAdd(long delta)164     public final long getAndAdd(long delta) {
165         return U.getAndAddLong(this, VALUE, delta);
166     }
167 
168     /**
169      * Atomically increments by one the current value.
170      *
171      * @return the updated value
172      */
incrementAndGet()173     public final long incrementAndGet() {
174         return U.getAndAddLong(this, VALUE, 1L) + 1L;
175     }
176 
177     /**
178      * Atomically decrements by one the current value.
179      *
180      * @return the updated value
181      */
decrementAndGet()182     public final long decrementAndGet() {
183         return U.getAndAddLong(this, VALUE, -1L) - 1L;
184     }
185 
186     /**
187      * Atomically adds the given value to the current value.
188      *
189      * @param delta the value to add
190      * @return the updated value
191      */
addAndGet(long delta)192     public final long addAndGet(long delta) {
193         return U.getAndAddLong(this, VALUE, delta) + delta;
194     }
195 
196     /**
197      * Atomically updates the current value with the results of
198      * applying the given function, returning the previous value. The
199      * function should be side-effect-free, since it may be re-applied
200      * when attempted updates fail due to contention among threads.
201      *
202      * @param updateFunction a side-effect-free function
203      * @return the previous value
204      * @since 1.8
205      */
getAndUpdate(LongUnaryOperator updateFunction)206     public final long getAndUpdate(LongUnaryOperator updateFunction) {
207         long prev, next;
208         do {
209             prev = get();
210             next = updateFunction.applyAsLong(prev);
211         } while (!compareAndSet(prev, next));
212         return prev;
213     }
214 
215     /**
216      * Atomically updates the current value with the results of
217      * applying the given function, returning the updated value. The
218      * function should be side-effect-free, since it may be re-applied
219      * when attempted updates fail due to contention among threads.
220      *
221      * @param updateFunction a side-effect-free function
222      * @return the updated value
223      * @since 1.8
224      */
updateAndGet(LongUnaryOperator updateFunction)225     public final long updateAndGet(LongUnaryOperator updateFunction) {
226         long prev, next;
227         do {
228             prev = get();
229             next = updateFunction.applyAsLong(prev);
230         } while (!compareAndSet(prev, next));
231         return next;
232     }
233 
234     /**
235      * Atomically updates the current value with the results of
236      * applying the given function to the current and given values,
237      * returning the previous value. The function should be
238      * side-effect-free, since it may be re-applied when attempted
239      * updates fail due to contention among threads.  The function
240      * is applied with the current value as its first argument,
241      * and the given update as the second argument.
242      *
243      * @param x the update value
244      * @param accumulatorFunction a side-effect-free function of two arguments
245      * @return the previous value
246      * @since 1.8
247      */
getAndAccumulate(long x, LongBinaryOperator accumulatorFunction)248     public final long getAndAccumulate(long x,
249                                        LongBinaryOperator accumulatorFunction) {
250         long prev, next;
251         do {
252             prev = get();
253             next = accumulatorFunction.applyAsLong(prev, x);
254         } while (!compareAndSet(prev, next));
255         return prev;
256     }
257 
258     /**
259      * Atomically updates the current value with the results of
260      * applying the given function to the current and given values,
261      * returning the updated value. The function should be
262      * side-effect-free, since it may be re-applied when attempted
263      * updates fail due to contention among threads.  The function
264      * is applied with the current value as its first argument,
265      * and the given update as the second argument.
266      *
267      * @param x the update value
268      * @param accumulatorFunction a side-effect-free function of two arguments
269      * @return the updated value
270      * @since 1.8
271      */
accumulateAndGet(long x, LongBinaryOperator accumulatorFunction)272     public final long accumulateAndGet(long x,
273                                        LongBinaryOperator accumulatorFunction) {
274         long prev, next;
275         do {
276             prev = get();
277             next = accumulatorFunction.applyAsLong(prev, x);
278         } while (!compareAndSet(prev, next));
279         return next;
280     }
281 
282     /**
283      * Returns the String representation of the current value.
284      * @return the String representation of the current value
285      */
toString()286     public String toString() {
287         return Long.toString(get());
288     }
289 
290     /**
291      * Returns the value of this {@code AtomicLong} as an {@code int}
292      * after a narrowing primitive conversion.
293      * @jls 5.1.3 Narrowing Primitive Conversions
294      */
intValue()295     public int intValue() {
296         return (int)get();
297     }
298 
299     /**
300      * Returns the value of this {@code AtomicLong} as a {@code long}.
301      * Equivalent to {@link #get()}.
302      */
longValue()303     public long longValue() {
304         return get();
305     }
306 
307     /**
308      * Returns the value of this {@code AtomicLong} as a {@code float}
309      * after a widening primitive conversion.
310      * @jls 5.1.2 Widening Primitive Conversions
311      */
floatValue()312     public float floatValue() {
313         return (float)get();
314     }
315 
316     /**
317      * Returns the value of this {@code AtomicLong} as a {@code double}
318      * after a widening primitive conversion.
319      * @jls 5.1.2 Widening Primitive Conversions
320      */
doubleValue()321     public double doubleValue() {
322         return (double)get();
323     }
324 
325 }
326