001 /*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
003 *
004 * This code is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU General Public License version 2 only, as
006 * published by the Free Software Foundation. Sun designates this
007 * particular file as subject to the "Classpath" exception as provided
008 * by Sun in the LICENSE file that accompanied this code.
009 *
010 * This code is distributed in the hope that it will be useful, but WITHOUT
011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
013 * version 2 for more details (a copy is included in the LICENSE file that
014 * accompanied this code).
015 *
016 * You should have received a copy of the GNU General Public License version
017 * 2 along with this work; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
019 *
020 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
021 * CA 95054 USA or visit www.sun.com if you need additional information or
022 * have any questions.
023 */
024
025 /*
026 * This file is available under and governed by the GNU General Public
027 * License version 2 only, as published by the Free Software Foundation.
028 * However, the following notice accompanied the original version of this
029 * file:
030 *
031 * Written by Doug Lea with assistance from members of JCP JSR-166
032 * Expert Group and released to the public domain, as explained at
033 * http://creativecommons.org/licenses/publicdomain
034 */
035
036 package java.util.concurrent.atomic;
037
038 import sun.misc.Unsafe;
039
040 /**
041 * A {@code long} value that may be updated atomically. See the
042 * {@link java.util.concurrent.atomic} package specification for
043 * description of the properties of atomic variables. An
044 * {@code AtomicLong} is used in applications such as atomically
045 * incremented sequence numbers, and cannot be used as a replacement
046 * for a {@link java.lang.Long}. However, this class does extend
047 * {@code Number} to allow uniform access by tools and utilities that
048 * deal with numerically-based classes.
049 *
050 * @since 1.5
051 * @author Doug Lea
052 */
053 public class AtomicLong extends Number implements java.io.Serializable {
054 private static final long serialVersionUID = 1927816293512124184L;
055
056 // setup to use Unsafe.compareAndSwapLong for updates
057 private static final Unsafe unsafe = Unsafe.getUnsafe();
058 private static final long valueOffset;
059
060 /**
061 * Records whether the underlying JVM supports lockless
062 * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
063 * method works in either case, some constructions should be
064 * handled at Java level to avoid locking user-visible locks.
065 */
066 static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
067
068 /**
069 * Returns whether underlying JVM supports lockless CompareAndSet
070 * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
071 */
072 private static native boolean VMSupportsCS8();
073
074 static {
075 try {
076 valueOffset = unsafe.objectFieldOffset(AtomicLong.class
077 .getDeclaredField("value"));
078 } catch (Exception ex) {
079 throw new Error(ex);
080 }
081 }
082
083 private volatile long value;
084
085 /**
086 * Creates a new AtomicLong with the given initial value.
087 *
088 * @param initialValue the initial value
089 */
090 public AtomicLong(long initialValue) {
091 value = initialValue;
092 }
093
094 /**
095 * Creates a new AtomicLong with initial value {@code 0}.
096 */
097 public AtomicLong() {
098 }
099
100 /**
101 * Gets the current value.
102 *
103 * @return the current value
104 */
105 public final long get() {
106 return value;
107 }
108
109 /**
110 * Sets to the given value.
111 *
112 * @param newValue the new value
113 */
114 public final void set(long newValue) {
115 value = newValue;
116 }
117
118 /**
119 * Eventually sets to the given value.
120 *
121 * @param newValue the new value
122 * @since 1.6
123 */
124 public final void lazySet(long newValue) {
125 unsafe.putOrderedLong(this , valueOffset, newValue);
126 }
127
128 /**
129 * Atomically sets to the given value and returns the old value.
130 *
131 * @param newValue the new value
132 * @return the previous value
133 */
134 public final long getAndSet(long newValue) {
135 while (true) {
136 long current = get();
137 if (compareAndSet(current, newValue))
138 return current;
139 }
140 }
141
142 /**
143 * Atomically sets the value to the given updated value
144 * if the current value {@code ==} the expected value.
145 *
146 * @param expect the expected value
147 * @param update the new value
148 * @return true if successful. False return indicates that
149 * the actual value was not equal to the expected value.
150 */
151 public final boolean compareAndSet(long expect, long update) {
152 return unsafe.compareAndSwapLong(this , valueOffset, expect,
153 update);
154 }
155
156 /**
157 * Atomically sets the value to the given updated value
158 * if the current value {@code ==} the expected value.
159 *
160 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
161 * and does not provide ordering guarantees, so is only rarely an
162 * appropriate alternative to {@code compareAndSet}.
163 *
164 * @param expect the expected value
165 * @param update the new value
166 * @return true if successful.
167 */
168 public final boolean weakCompareAndSet(long expect, long update) {
169 return unsafe.compareAndSwapLong(this , valueOffset, expect,
170 update);
171 }
172
173 /**
174 * Atomically increments by one the current value.
175 *
176 * @return the previous value
177 */
178 public final long getAndIncrement() {
179 while (true) {
180 long current = get();
181 long next = current + 1;
182 if (compareAndSet(current, next))
183 return current;
184 }
185 }
186
187 /**
188 * Atomically decrements by one the current value.
189 *
190 * @return the previous value
191 */
192 public final long getAndDecrement() {
193 while (true) {
194 long current = get();
195 long next = current - 1;
196 if (compareAndSet(current, next))
197 return current;
198 }
199 }
200
201 /**
202 * Atomically adds the given value to the current value.
203 *
204 * @param delta the value to add
205 * @return the previous value
206 */
207 public final long getAndAdd(long delta) {
208 while (true) {
209 long current = get();
210 long next = current + delta;
211 if (compareAndSet(current, next))
212 return current;
213 }
214 }
215
216 /**
217 * Atomically increments by one the current value.
218 *
219 * @return the updated value
220 */
221 public final long incrementAndGet() {
222 for (;;) {
223 long current = get();
224 long next = current + 1;
225 if (compareAndSet(current, next))
226 return next;
227 }
228 }
229
230 /**
231 * Atomically decrements by one the current value.
232 *
233 * @return the updated value
234 */
235 public final long decrementAndGet() {
236 for (;;) {
237 long current = get();
238 long next = current - 1;
239 if (compareAndSet(current, next))
240 return next;
241 }
242 }
243
244 /**
245 * Atomically adds the given value to the current value.
246 *
247 * @param delta the value to add
248 * @return the updated value
249 */
250 public final long addAndGet(long delta) {
251 for (;;) {
252 long current = get();
253 long next = current + delta;
254 if (compareAndSet(current, next))
255 return next;
256 }
257 }
258
259 /**
260 * Returns the String representation of the current value.
261 * @return the String representation of the current value.
262 */
263 public String toString() {
264 return Long.toString(get());
265 }
266
267 public int intValue() {
268 return (int) get();
269 }
270
271 public long longValue() {
272 return (long) get();
273 }
274
275 public float floatValue() {
276 return (float) get();
277 }
278
279 public double doubleValue() {
280 return (double) get();
281 }
282
283 }
|