Home | History | Annotate | Download | only in atomic
      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/licenses/publicdomain
      5  */
      6 
      7 package java.util.concurrent.atomic;
      8 import 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  */
     23 public 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 = UnsafeAccess.THE_ONE; // android-changed
     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>May <a href="package-summary.html#Spurious">fail spuriously</a>
    128      * and does not provide ordering guarantees, so is only rarely an
    129      * 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     public int intValue() {
    235         return (int)get();
    236     }
    237 
    238     public long longValue() {
    239         return get();
    240     }
    241 
    242     public float floatValue() {
    243         return (float)get();
    244     }
    245 
    246     public double doubleValue() {
    247         return (double)get();
    248     }
    249 
    250 }
    251