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
7package java.util.concurrent.atomic;
8
9import java.util.function.LongBinaryOperator;
10import 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 */
25public 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     */
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     */
61    public AtomicLong(long initialValue) {
62        value = initialValue;
63    }
64
65    /**
66     * Creates a new AtomicLong with initial value {@code 0}.
67     */
68    public AtomicLong() {
69    }
70
71    /**
72     * Gets the current value.
73     *
74     * @return the current value
75     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
321    public double doubleValue() {
322        return (double)get();
323    }
324
325}
326