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 * An {@code int} 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 AtomicInteger} is used in applications such as atomically
045 * incremented counters, and cannot be used as a replacement for an
046 * {@link java.lang.Integer}. 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 AtomicInteger extends Number implements
054 java.io.Serializable {
055 private static final long serialVersionUID = 6214790243416807050L;
056
057 // setup to use Unsafe.compareAndSwapInt for updates
058 private static final Unsafe unsafe = Unsafe.getUnsafe();
059 private static final long valueOffset;
060
061 static {
062 try {
063 valueOffset = unsafe.objectFieldOffset(AtomicInteger.class
064 .getDeclaredField("value"));
065 } catch (Exception ex) {
066 throw new Error(ex);
067 }
068 }
069
070 private volatile int value;
071
072 /**
073 * Creates a new AtomicInteger with the given initial value.
074 *
075 * @param initialValue the initial value
076 */
077 public AtomicInteger(int initialValue) {
078 value = initialValue;
079 }
080
081 /**
082 * Creates a new AtomicInteger with initial value {@code 0}.
083 */
084 public AtomicInteger() {
085 }
086
087 /**
088 * Gets the current value.
089 *
090 * @return the current value
091 */
092 public final int get() {
093 return value;
094 }
095
096 /**
097 * Sets to the given value.
098 *
099 * @param newValue the new value
100 */
101 public final void set(int newValue) {
102 value = newValue;
103 }
104
105 /**
106 * Eventually sets to the given value.
107 *
108 * @param newValue the new value
109 * @since 1.6
110 */
111 public final void lazySet(int newValue) {
112 unsafe.putOrderedInt(this , valueOffset, newValue);
113 }
114
115 /**
116 * Atomically sets to the given value and returns the old value.
117 *
118 * @param newValue the new value
119 * @return the previous value
120 */
121 public final int getAndSet(int newValue) {
122 for (;;) {
123 int current = get();
124 if (compareAndSet(current, newValue))
125 return current;
126 }
127 }
128
129 /**
130 * Atomically sets the value to the given updated value
131 * if the current value {@code ==} the expected value.
132 *
133 * @param expect the expected value
134 * @param update the new value
135 * @return true if successful. False return indicates that
136 * the actual value was not equal to the expected value.
137 */
138 public final boolean compareAndSet(int expect, int update) {
139 return unsafe.compareAndSwapInt(this , valueOffset, expect,
140 update);
141 }
142
143 /**
144 * Atomically sets the value to the given updated value
145 * if the current value {@code ==} the expected value.
146 *
147 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
148 * and does not provide ordering guarantees, so is only rarely an
149 * appropriate alternative to {@code compareAndSet}.
150 *
151 * @param expect the expected value
152 * @param update the new value
153 * @return true if successful.
154 */
155 public final boolean weakCompareAndSet(int expect, int update) {
156 return unsafe.compareAndSwapInt(this , valueOffset, expect,
157 update);
158 }
159
160 /**
161 * Atomically increments by one the current value.
162 *
163 * @return the previous value
164 */
165 public final int getAndIncrement() {
166 for (;;) {
167 int current = get();
168 int next = current + 1;
169 if (compareAndSet(current, next))
170 return current;
171 }
172 }
173
174 /**
175 * Atomically decrements by one the current value.
176 *
177 * @return the previous value
178 */
179 public final int getAndDecrement() {
180 for (;;) {
181 int current = get();
182 int next = current - 1;
183 if (compareAndSet(current, next))
184 return current;
185 }
186 }
187
188 /**
189 * Atomically adds the given value to the current value.
190 *
191 * @param delta the value to add
192 * @return the previous value
193 */
194 public final int getAndAdd(int delta) {
195 for (;;) {
196 int current = get();
197 int next = current + delta;
198 if (compareAndSet(current, next))
199 return current;
200 }
201 }
202
203 /**
204 * Atomically increments by one the current value.
205 *
206 * @return the updated value
207 */
208 public final int incrementAndGet() {
209 for (;;) {
210 int current = get();
211 int next = current + 1;
212 if (compareAndSet(current, next))
213 return next;
214 }
215 }
216
217 /**
218 * Atomically decrements by one the current value.
219 *
220 * @return the updated value
221 */
222 public final int decrementAndGet() {
223 for (;;) {
224 int current = get();
225 int next = current - 1;
226 if (compareAndSet(current, next))
227 return next;
228 }
229 }
230
231 /**
232 * Atomically adds the given value to the current value.
233 *
234 * @param delta the value to add
235 * @return the updated value
236 */
237 public final int addAndGet(int delta) {
238 for (;;) {
239 int current = get();
240 int next = current + delta;
241 if (compareAndSet(current, next))
242 return next;
243 }
244 }
245
246 /**
247 * Returns the String representation of the current value.
248 * @return the String representation of the current value.
249 */
250 public String toString() {
251 return Integer.toString(get());
252 }
253
254 public int intValue() {
255 return get();
256 }
257
258 public long longValue() {
259 return (long) get();
260 }
261
262 public float floatValue() {
263 return (float) get();
264 }
265
266 public double doubleValue() {
267 return (double) get();
268 }
269
270 }
|