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