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 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         return unsafe.getAndSetLong(this, valueOffset, newValue);
 133     }
 134 
 135     /**
 136      * Atomically sets the value to the given updated value
 137      * if the current value {@code ==} the expected value.
 138      *
 139      * @param expect the expected value
 140      * @param update the new value
 141      * @return true if successful. False return indicates that
 142      * the actual value was not equal to the expected value.
 143      */
 144     public final boolean compareAndSet(long expect, long update) {
 145         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
 146     }
 147 
 148     /**
 149      * Atomically sets the value to the given updated value
 150      * if the current value {@code ==} the expected value.
 151      *
 152      * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 153      * and does not provide ordering guarantees, so is only rarely an
 154      * appropriate alternative to {@code compareAndSet}.
 155      *
 156      * @param expect the expected value
 157      * @param update the new value
 158      * @return true if successful
 159      */
 160     public final boolean weakCompareAndSet(long expect, long update) {
 161         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
 162     }
 163 
 164     /**
 165      * Atomically increments by one the current value.
 166      *
 167      * @return the previous value
 168      */
 169     public final long getAndIncrement() {
 170         return getAndAdd(1);
 171     }
 172 
 173     /**
 174      * Atomically decrements by one the current value.
 175      *
 176      * @return the previous value
 177      */
 178     public final long getAndDecrement() {
 179         return getAndAdd(-1);
 180     }
 181 
 182     /**
 183      * Atomically adds the given value to the current value.
 184      *
 185      * @param delta the value to add
 186      * @return the previous value
 187      */
 188     public final long getAndAdd(long delta) {
 189         return unsafe.getAndAddLong(this, valueOffset, delta);
 190     }
 191 
 192     /**
 193      * Atomically increments by one the current value.
 194      *
 195      * @return the updated value
 196      */
 197     public final long incrementAndGet() {
 198         return getAndAdd(1) + 1;
 199     }
 200 
 201     /**
 202      * Atomically decrements by one the current value.
 203      *
 204      * @return the updated value
 205      */
 206     public final long decrementAndGet() {
 207         return getAndAdd(-1) - 1;
 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         return getAndAdd(delta) + delta;
 218     }
 219 
 220     /**
 221      * Returns the String representation of the current value.
 222      * @return the String representation of the current value
 223      */
 224     public String toString() {
 225         return Long.toString(get());
 226     }
 227 
 228     /**
 229      * Returns the value of this {@code AtomicLong} as an {@code int}
 230      * after a narrowing primitive conversion.
 231      * @jls 5.1.3 Narrowing Primitive Conversions
 232      */
 233     public int intValue() {
 234         return (int)get();
 235     }
 236 
 237     /**
 238      * Returns the value of this {@code AtomicLong} as a {@code long}.
 239      */
 240     public long longValue() {
 241         return get();
 242     }
 243 
 244     /**
 245      * Returns the value of this {@code AtomicLong} as a {@code float}
 246      * after a widening primitive conversion.
 247      * @jls 5.1.2 Widening Primitive Conversions
 248      */
 249     public float floatValue() {
 250         return (float)get();
 251     }
 252 
 253     /**
 254      * Returns the value of this {@code AtomicLong} as a {@code double}
 255      * after a widening primitive conversion.
 256      * @jls 5.1.2 Widening Primitive Conversions
 257      */
 258     public double doubleValue() {
 259         return (double)get();
 260     }
 261 
 262 }