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