jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     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.  Sun designates this
       
     7  * particular file as subject to the "Classpath" exception as provided
       
     8  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    21  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    22  * have any 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/licenses/publicdomain
       
    34  */
       
    35 
       
    36 package java.util.concurrent.atomic;
       
    37 import sun.misc.Unsafe;
       
    38 
       
    39 /**
       
    40  * A {@code long} value that may be updated atomically.  See the
       
    41  * {@link java.util.concurrent.atomic} package specification for
       
    42  * description of the properties of atomic variables. An
       
    43  * {@code AtomicLong} is used in applications such as atomically
       
    44  * incremented sequence numbers, and cannot be used as a replacement
       
    45  * for a {@link java.lang.Long}. However, this class does extend
       
    46  * {@code Number} to allow uniform access by tools and utilities that
       
    47  * deal with numerically-based classes.
       
    48  *
       
    49  * @since 1.5
       
    50  * @author Doug Lea
       
    51  */
       
    52 public class AtomicLong extends Number implements java.io.Serializable {
       
    53     private static final long serialVersionUID = 1927816293512124184L;
       
    54 
       
    55     // setup to use Unsafe.compareAndSwapLong for updates
       
    56     private static final Unsafe unsafe = Unsafe.getUnsafe();
       
    57     private static final long valueOffset;
       
    58 
       
    59     /**
       
    60      * Records whether the underlying JVM supports lockless
       
    61      * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
       
    62      * method works in either case, some constructions should be
       
    63      * handled at Java level to avoid locking user-visible locks.
       
    64      */
       
    65     static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
       
    66 
       
    67     /**
       
    68      * Returns whether underlying JVM supports lockless CompareAndSet
       
    69      * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
       
    70      */
       
    71     private static native boolean VMSupportsCS8();
       
    72 
       
    73     static {
       
    74       try {
       
    75         valueOffset = unsafe.objectFieldOffset
       
    76             (AtomicLong.class.getDeclaredField("value"));
       
    77       } catch (Exception ex) { throw new Error(ex); }
       
    78     }
       
    79 
       
    80     private volatile long value;
       
    81 
       
    82     /**
       
    83      * Creates a new AtomicLong with the given initial value.
       
    84      *
       
    85      * @param initialValue the initial value
       
    86      */
       
    87     public AtomicLong(long initialValue) {
       
    88         value = initialValue;
       
    89     }
       
    90 
       
    91     /**
       
    92      * Creates a new AtomicLong with initial value {@code 0}.
       
    93      */
       
    94     public AtomicLong() {
       
    95     }
       
    96 
       
    97     /**
       
    98      * Gets the current value.
       
    99      *
       
   100      * @return the current value
       
   101      */
       
   102     public final long get() {
       
   103         return value;
       
   104     }
       
   105 
       
   106     /**
       
   107      * Sets to the given value.
       
   108      *
       
   109      * @param newValue the new value
       
   110      */
       
   111     public final void set(long newValue) {
       
   112         value = newValue;
       
   113     }
       
   114 
       
   115     /**
       
   116      * Eventually sets to the given value.
       
   117      *
       
   118      * @param newValue the new value
       
   119      * @since 1.6
       
   120      */
       
   121     public final void lazySet(long newValue) {
       
   122         unsafe.putOrderedLong(this, valueOffset, newValue);
       
   123     }
       
   124 
       
   125     /**
       
   126      * Atomically sets to the given value and returns the old value.
       
   127      *
       
   128      * @param newValue the new value
       
   129      * @return the previous value
       
   130      */
       
   131     public final long getAndSet(long newValue) {
       
   132         while (true) {
       
   133             long current = get();
       
   134             if (compareAndSet(current, newValue))
       
   135                 return current;
       
   136         }
       
   137     }
       
   138 
       
   139     /**
       
   140      * Atomically sets the value to the given updated value
       
   141      * if the current value {@code ==} the expected value.
       
   142      *
       
   143      * @param expect the expected value
       
   144      * @param update the new value
       
   145      * @return true if successful. False return indicates that
       
   146      * the actual value was not equal to the expected value.
       
   147      */
       
   148     public final boolean compareAndSet(long expect, long update) {
       
   149         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
       
   150     }
       
   151 
       
   152     /**
       
   153      * Atomically sets the value to the given updated value
       
   154      * if the current value {@code ==} the expected value.
       
   155      *
       
   156      * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
       
   157      * and does not provide ordering guarantees, so is only rarely an
       
   158      * appropriate alternative to {@code compareAndSet}.
       
   159      *
       
   160      * @param expect the expected value
       
   161      * @param update the new value
       
   162      * @return true if successful.
       
   163      */
       
   164     public final boolean weakCompareAndSet(long expect, long update) {
       
   165         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
       
   166     }
       
   167 
       
   168     /**
       
   169      * Atomically increments by one the current value.
       
   170      *
       
   171      * @return the previous value
       
   172      */
       
   173     public final long getAndIncrement() {
       
   174         while (true) {
       
   175             long current = get();
       
   176             long next = current + 1;
       
   177             if (compareAndSet(current, next))
       
   178                 return current;
       
   179         }
       
   180     }
       
   181 
       
   182     /**
       
   183      * Atomically decrements by one the current value.
       
   184      *
       
   185      * @return the previous value
       
   186      */
       
   187     public final long getAndDecrement() {
       
   188         while (true) {
       
   189             long current = get();
       
   190             long next = current - 1;
       
   191             if (compareAndSet(current, next))
       
   192                 return current;
       
   193         }
       
   194     }
       
   195 
       
   196     /**
       
   197      * Atomically adds the given value to the current value.
       
   198      *
       
   199      * @param delta the value to add
       
   200      * @return the previous value
       
   201      */
       
   202     public final long getAndAdd(long delta) {
       
   203         while (true) {
       
   204             long current = get();
       
   205             long next = current + delta;
       
   206             if (compareAndSet(current, next))
       
   207                 return current;
       
   208         }
       
   209     }
       
   210 
       
   211     /**
       
   212      * Atomically increments by one the current value.
       
   213      *
       
   214      * @return the updated value
       
   215      */
       
   216     public final long incrementAndGet() {
       
   217         for (;;) {
       
   218             long current = get();
       
   219             long next = current + 1;
       
   220             if (compareAndSet(current, next))
       
   221                 return next;
       
   222         }
       
   223     }
       
   224 
       
   225     /**
       
   226      * Atomically decrements by one the current value.
       
   227      *
       
   228      * @return the updated value
       
   229      */
       
   230     public final long decrementAndGet() {
       
   231         for (;;) {
       
   232             long current = get();
       
   233             long next = current - 1;
       
   234             if (compareAndSet(current, next))
       
   235                 return next;
       
   236         }
       
   237     }
       
   238 
       
   239     /**
       
   240      * Atomically adds the given value to the current value.
       
   241      *
       
   242      * @param delta the value to add
       
   243      * @return the updated value
       
   244      */
       
   245     public final long addAndGet(long delta) {
       
   246         for (;;) {
       
   247             long current = get();
       
   248             long next = current + delta;
       
   249             if (compareAndSet(current, next))
       
   250                 return next;
       
   251         }
       
   252     }
       
   253 
       
   254     /**
       
   255      * Returns the String representation of the current value.
       
   256      * @return the String representation of the current value.
       
   257      */
       
   258     public String toString() {
       
   259         return Long.toString(get());
       
   260     }
       
   261 
       
   262 
       
   263     public int intValue() {
       
   264         return (int)get();
       
   265     }
       
   266 
       
   267     public long longValue() {
       
   268         return get();
       
   269     }
       
   270 
       
   271     public float floatValue() {
       
   272         return (float)get();
       
   273     }
       
   274 
       
   275     public double doubleValue() {
       
   276         return (double)get();
       
   277     }
       
   278 
       
   279 }