content: /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  /*
   * This file is available under and governed by the GNU General Public
   * License version 2 only, as published by the Free Software Foundation.
   * However, the following notice accompanied the original version of this
   * file:
   *
   * Written by Doug Lea with assistance from members of JCP JSR-166
   * Expert Group and released to the public domain, as explained at
   * http://creativecommons.org/publicdomain/zero/1.0/
   */
  
  package java.util.concurrent.atomic;
  
  import java.util.function.BinaryOperator;
  import java.util.function.UnaryOperator;
  
  /**
   * An object reference that may be updated atomically. See the {@link
   * java.util.concurrent.atomic} package specification for description
   * of the properties of atomic variables.
   * @since 1.5
   * @author Doug Lea
   * @param <V> The type of object referred to by this reference
   */
  public class AtomicReference<V> implements java.io.Serializable {
      private static final long serialVersionUID = -1848883965231344442L;
  
      private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
      private static final long VALUE;
  
      static {
          try {
              VALUE = U.objectFieldOffset
                  (AtomicReference.class.getDeclaredField("value"));
          } catch (ReflectiveOperationException e) {
              throw new Error(e);
          }
      }
  
      private volatile V value;
  
      /**
       * Creates a new AtomicReference with the given initial value.
       *
       * @param initialValue the initial value
       */
      public AtomicReference(V initialValue) {
          value = initialValue;
      }
  
      /**
       * Creates a new AtomicReference with null initial value.
       */
      public AtomicReference() {
      }
  
      /**
       * Gets the current value.
       *
       * @return the current value
       */
      public final V get() {
          return value;
      }
  
      /**
       * Sets to the given value.
       *
       * @param newValue the new value
       */
      public final void set(V newValue) {
          value = newValue;
      }
  
      /**
       * Eventually sets to the given value.
       *
       * @param newValue the new value
       * @since 1.6
       */
      public final void lazySet(V newValue) {
          U.putOrderedObject(this, VALUE, newValue);
      }
  
      /**
       * Atomically sets the value to the given updated value
       * if the current value {@code ==} the expected value.
       * @param expect the expected value
       * @param update the new value
       * @return {@code true} if successful. False return indicates that
       * the actual value was not equal to the expected value.
       */
      public final boolean compareAndSet(V expect, V update) {
          return U.compareAndSwapObject(this, VALUE, expect, update);
      }
  
      /**
       * Atomically sets the value to the given updated value
       * if the current value {@code ==} the expected value.
       *
       * <p><a href="package-summary.html#weakCompareAndSet">May fail
       * spuriously and does not provide ordering guarantees</a>, so is
       * only rarely an appropriate alternative to {@code compareAndSet}.
       *
       * @param expect the expected value
       * @param update the new value
       * @return {@code true} if successful
       */
      public final boolean weakCompareAndSet(V expect, V update) {
          return U.compareAndSwapObject(this, VALUE, expect, update);
      }
  
      /**
       * Atomically sets to the given value and returns the old value.
       *
       * @param newValue the new value
       * @return the previous value
       */
      @SuppressWarnings("unchecked")
      public final V getAndSet(V newValue) {
          return (V)U.getAndSetObject(this, VALUE, newValue);
      }
  
      /**
       * Atomically updates the current value with the results of
       * applying the given function, returning the previous value. The
       * function should be side-effect-free, since it may be re-applied
       * when attempted updates fail due to contention among threads.
       *
       * @param updateFunction a side-effect-free function
       * @return the previous value
       * @since 1.8
       */
      public final V getAndUpdate(UnaryOperator<V> updateFunction) {
          V prev, next;
          do {
              prev = get();
              next = updateFunction.apply(prev);
          } while (!compareAndSet(prev, next));
          return prev;
      }
  
      /**
       * Atomically updates the current value with the results of
       * applying the given function, returning the updated value. The
       * function should be side-effect-free, since it may be re-applied
       * when attempted updates fail due to contention among threads.
       *
       * @param updateFunction a side-effect-free function
       * @return the updated value
       * @since 1.8
       */
      public final V updateAndGet(UnaryOperator<V> updateFunction) {
          V prev, next;
          do {
              prev = get();
              next = updateFunction.apply(prev);
          } while (!compareAndSet(prev, next));
          return next;
      }
  
      /**
       * Atomically updates the current value with the results of
       * applying the given function to the current and given values,
       * returning the previous value. The function should be
       * side-effect-free, since it may be re-applied when attempted
       * updates fail due to contention among threads.  The function
       * is applied with the current value as its first argument,
       * and the given update as the second argument.
       *
       * @param x the update value
       * @param accumulatorFunction a side-effect-free function of two arguments
       * @return the previous value
       * @since 1.8
       */
      public final V getAndAccumulate(V x,
                                      BinaryOperator<V> accumulatorFunction) {
          V prev, next;
          do {
              prev = get();
              next = accumulatorFunction.apply(prev, x);
          } while (!compareAndSet(prev, next));
          return prev;
      }
  
      /**
       * Atomically updates the current value with the results of
       * applying the given function to the current and given values,
       * returning the updated value. The function should be
       * side-effect-free, since it may be re-applied when attempted
       * updates fail due to contention among threads.  The function
       * is applied with the current value as its first argument,
       * and the given update as the second argument.
       *
       * @param x the update value
       * @param accumulatorFunction a side-effect-free function of two arguments
       * @return the updated value
       * @since 1.8
       */
      public final V accumulateAndGet(V x,
                                      BinaryOperator<V> accumulatorFunction) {
          V prev, next;
          do {
              prev = get();
              next = accumulatorFunction.apply(prev, x);
          } while (!compareAndSet(prev, next));
          return next;
      }
  
      /**
       * Returns the String representation of the current value.
       * @return the String representation of the current value
       */
      public String toString() {
          return String.valueOf(get());
      }
  
  }
  