1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/publicdomain/zero/1.0/
  34  */
  35 
  36 package java.util.concurrent.atomic;
  37 import java.util.functions.IntUnaryOperator;
  38 import sun.misc.Unsafe;
  39 
  40 /**
  41  * An {@code int} value that may be updated atomically.  See the
  42  * {@link java.util.concurrent.atomic} package specification for
  43  * description of the properties of atomic variables. An
  44  * {@code AtomicInteger} is used in applications such as atomically
  45  * incremented counters, and cannot be used as a replacement for an
  46  * {@link java.lang.Integer}. However, this class does extend
  47  * {@code Number} to allow uniform access by tools and utilities that
  48  * deal with numerically-based classes.
  49  *
  50  * @since 1.5
  51  * @author Doug Lea
  52 */
  53 public class AtomicInteger extends Number implements java.io.Serializable {
  54     private static final long serialVersionUID = 6214790243416807050L;
  55 
  56     // setup to use Unsafe.compareAndSwapInt for updates
  57     private static final Unsafe unsafe = Unsafe.getUnsafe();
  58     private static final long valueOffset;
  59 
  60     static {
  61         try {
  62             valueOffset = unsafe.objectFieldOffset
  63                 (AtomicInteger.class.getDeclaredField("value"));
  64         } catch (Exception ex) { throw new Error(ex); }
  65     }
  66 
  67     private volatile int value;
  68 
  69     /**
  70      * Creates a new AtomicInteger with the given initial value.
  71      *
  72      * @param initialValue the initial value
  73      */
  74     public AtomicInteger(int initialValue) {
  75         value = initialValue;
  76     }
  77 
  78     /**
  79      * Creates a new AtomicInteger with initial value {@code 0}.
  80      */
  81     public AtomicInteger() {
  82     }
  83 
  84     /**
  85      * Gets the current value.
  86      *
  87      * @return the current value
  88      */
  89     public final int get() {
  90         return value;
  91     }
  92 
  93     /**
  94      * Sets to the given value.
  95      *
  96      * @param newValue the new value
  97      */
  98     public final void set(int newValue) {
  99         value = newValue;
 100     }
 101 
 102     /**
 103      * Eventually sets to the given value.
 104      *
 105      * @param newValue the new value
 106      * @since 1.6
 107      */
 108     public final void lazySet(int newValue) {
 109         unsafe.putOrderedInt(this, valueOffset, newValue);
 110     }
 111 
 112     /**
 113      * Atomically sets to the given value and returns the old value.
 114      *
 115      * @param newValue the new value
 116      * @return the previous value
 117      */
 118     public final int getAndSet(int newValue) {
 119         for (;;) {
 120             int current = get();
 121             if (compareAndSet(current, newValue))
 122                 return current;
 123         }
 124     }
 125 
 126     /**
 127      * Atomically sets the value to the given updated value
 128      * if the current value {@code ==} the expected value.
 129      *
 130      * @param expect the expected value
 131      * @param update the new value
 132      * @return true if successful. False return indicates that
 133      * the actual value was not equal to the expected value.
 134      */
 135     public final boolean compareAndSet(int expect, int update) {
 136         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
 137     }
 138 
 139     /**
 140      * Sets the value by applying the supplied operator to the old value,
 141      * and updating it atomically as in {@link #compareAndSet(int, int)}.
 142      * 
 143      * If the update results in a collision, we back off and retry the update 
 144      * (using the new current value) until successful. 
 145      * 
 146      * @param op the operator to use to compute the new value
 147      * @return the old value
 148      */
 149     public final int getAndUpdate(IntUnaryOperator op) {
 150         int oldValue, newValue;
 151         do {
 152             oldValue = get();
 153             newValue = op.operate(oldValue);
 154         } while (!compareAndSet(oldValue, newValue));
 155         return oldValue;
 156     }
 157 
 158     /**
 159      * Sets the value by applying the supplied operator to the old value,
 160      * and updating it atomically as in {@link #compareAndSet(int, int)}.
 161      * 
 162      * If the update results in a collision, we back off and retry the update 
 163      * (using the new current value) until successful. 
 164      * 
 165      * @param op the operator to use to compute the new value
 166      * @return the new value
 167      */
 168     public final int updateAndGet(IntUnaryOperator op) {
 169         int oldValue, newValue;
 170         do {
 171             oldValue = get();
 172             newValue = op.operate(oldValue);
 173         } while (!compareAndSet(oldValue, newValue));
 174         return newValue;
 175     }
 176     
 177     /**
 178      * Atomically sets the value to the given updated value
 179      * if the current value {@code ==} the expected value.
 180      *
 181      * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 182      * and does not provide ordering guarantees, so is only rarely an
 183      * appropriate alternative to {@code compareAndSet}.
 184      *
 185      * @param expect the expected value
 186      * @param update the new value
 187      * @return true if successful.
 188      */
 189     public final boolean weakCompareAndSet(int expect, int update) {
 190         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
 191     }
 192 
 193     /**
 194      * Atomically increments by one the current value.
 195      *
 196      * @return the previous value
 197      */
 198     public final int getAndIncrement() {
 199         for (;;) {
 200             int current = get();
 201             int next = current + 1;
 202             if (compareAndSet(current, next))
 203                 return current;
 204         }
 205     }
 206 
 207     /**
 208      * Atomically decrements by one the current value.
 209      *
 210      * @return the previous value
 211      */
 212     public final int getAndDecrement() {
 213         for (;;) {
 214             int current = get();
 215             int next = current - 1;
 216             if (compareAndSet(current, next))
 217                 return current;
 218         }
 219     }
 220 
 221     /**
 222      * Atomically adds the given value to the current value.
 223      *
 224      * @param delta the value to add
 225      * @return the previous value
 226      */
 227     public final int getAndAdd(int delta) {
 228         for (;;) {
 229             int current = get();
 230             int next = current + delta;
 231             if (compareAndSet(current, next))
 232                 return current;
 233         }
 234     }
 235 
 236     /**
 237      * Atomically increments by one the current value.
 238      *
 239      * @return the updated value
 240      */
 241     public final int incrementAndGet() {
 242         for (;;) {
 243             int current = get();
 244             int next = current + 1;
 245             if (compareAndSet(current, next))
 246                 return next;
 247         }
 248     }
 249 
 250     /**
 251      * Atomically decrements by one the current value.
 252      *
 253      * @return the updated value
 254      */
 255     public final int decrementAndGet() {
 256         for (;;) {
 257             int current = get();
 258             int next = current - 1;
 259             if (compareAndSet(current, next))
 260                 return next;
 261         }
 262     }
 263 
 264     /**
 265      * Atomically adds the given value to the current value.
 266      *
 267      * @param delta the value to add
 268      * @return the updated value
 269      */
 270     public final int addAndGet(int delta) {
 271         for (;;) {
 272             int current = get();
 273             int next = current + delta;
 274             if (compareAndSet(current, next))
 275                 return next;
 276         }
 277     }
 278 
 279     /**
 280      * Returns the String representation of the current value.
 281      * @return the String representation of the current value.
 282      */
 283     public String toString() {
 284         return Integer.toString(get());
 285     }
 286 
 287 
 288     /**
 289      * Returns the value of this {@code AtomicInteger} as an {@code int}.
 290      */
 291     public int intValue() {
 292         return get();
 293     }
 294 
 295     /**
 296      * Returns the value of this {@code AtomicInteger} as a {@code long}
 297      * after a widening primitive conversion.
 298      * @jls 5.1.2 Widening Primitive Conversions
 299      */
 300     public long longValue() {
 301         return (long)get();
 302     }
 303 
 304     /**
 305      * Returns the value of this {@code AtomicInteger} as a {@code float}
 306      * after a widening primitive conversion.
 307      * @jls 5.1.2 Widening Primitive Conversions
 308      */
 309     public float floatValue() {
 310         return (float)get();
 311     }
 312 
 313     /**
 314      * Returns the value of this {@code AtomicInteger} as a {@code double}
 315      * after a widening primitive conversion.
 316      * @jls 5.1.2 Widening Primitive Conversions
 317      */
 318     public double doubleValue() {
 319         return (double)get();
 320     }
 321 
 322 }