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.lang.reflect.Field;
  import java.lang.reflect.Modifier;
  import java.security.AccessController;
  import java.security.PrivilegedActionException;
  import java.security.PrivilegedExceptionAction;
  import java.util.function.IntBinaryOperator;
  import java.util.function.IntUnaryOperator;
  import sun.reflect.CallerSensitive;
  import sun.reflect.Reflection;
  
  /**
   * A reflection-based utility that enables atomic updates to
   * designated {@code volatile int} fields of designated classes.
   * This class is designed for use in atomic data structures in which
   * several fields of the same node are independently subject to atomic
   * updates.
   *
   * <p>Note that the guarantees of the {@code compareAndSet}
   * method in this class are weaker than in other atomic classes.
   * Because this class cannot ensure that all uses of the field
   * are appropriate for purposes of atomic access, it can
   * guarantee atomicity only with respect to other invocations of
   * {@code compareAndSet} and {@code set} on the same updater.
   *
   * @since 1.5
   * @author Doug Lea
   * @param <T> The type of the object holding the updatable field
   */
  public abstract class AtomicIntegerFieldUpdater<T> {
      /**
       * Creates and returns an updater for objects with the given field.
       * The Class argument is needed to check that reflective types and
       * generic types match.
       *
       * @param tclass the class of the objects holding the field
       * @param fieldName the name of the field to be updated
       * @param <U> the type of instances of tclass
       * @return the updater
       * @throws IllegalArgumentException if the field is not a
       * volatile integer type
       * @throws RuntimeException with a nested reflection-based
       * exception if the class does not hold field or is the wrong type,
       * or the field is inaccessible to the caller according to Java language
       * access control
       */
      @CallerSensitive
      public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
                                                                String fieldName) {
          return new AtomicIntegerFieldUpdaterImpl<U>
              (tclass, fieldName, Reflection.getCallerClass());
      }
  
      /**
       * Protected do-nothing constructor for use by subclasses.
       */
      protected AtomicIntegerFieldUpdater() {
      }
  
      /**
       * Atomically sets the field of the given object managed by this updater
       * to the given updated value if the current value {@code ==} the
       * expected value. This method is guaranteed to be atomic with respect to
       * other calls to {@code compareAndSet} and {@code set}, but not
       * necessarily with respect to other changes in the field.
       *
       * @param obj An object whose field to conditionally set
       * @param expect the expected value
       * @param update the new value
       * @return {@code true} if successful
       * @throws ClassCastException if {@code obj} is not an instance
       * of the class possessing the field established in the constructor
       */
      public abstract boolean compareAndSet(T obj, int expect, int update);
  
      /**
       * Atomically sets the field of the given object managed by this updater
       * to the given updated value if the current value {@code ==} the
       * expected value. This method is guaranteed to be atomic with respect to
       * other calls to {@code compareAndSet} and {@code set}, but not
       * necessarily with respect to other changes in the field.
       *
       * <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 obj An object whose field to conditionally set
       * @param expect the expected value
       * @param update the new value
       * @return {@code true} if successful
       * @throws ClassCastException if {@code obj} is not an instance
       * of the class possessing the field established in the constructor
       */
      public abstract boolean weakCompareAndSet(T obj, int expect, int update);
  
      /**
       * Sets the field of the given object managed by this updater to the
       * given updated value. This operation is guaranteed to act as a volatile
       * store with respect to subsequent invocations of {@code compareAndSet}.
       *
       * @param obj An object whose field to set
       * @param newValue the new value
       */
      public abstract void set(T obj, int newValue);
  
      /**
       * Eventually sets the field of the given object managed by this
       * updater to the given updated value.
       *
       * @param obj An object whose field to set
       * @param newValue the new value
       * @since 1.6
       */
      public abstract void lazySet(T obj, int newValue);
  
      /**
       * Gets the current value held in the field of the given object managed
       * by this updater.
       *
       * @param obj An object whose field to get
       * @return the current value
       */
      public abstract int get(T obj);
  
      /**
       * Atomically sets the field of the given object managed by this updater
       * to the given value and returns the old value.
       *
       * @param obj An object whose field to get and set
       * @param newValue the new value
       * @return the previous value
       */
      public int getAndSet(T obj, int newValue) {
          int prev;
          do {
              prev = get(obj);
          } while (!compareAndSet(obj, prev, newValue));
          return prev;
      }
  
      /**
       * Atomically increments by one the current value of the field of the
       * given object managed by this updater.
       *
       * @param obj An object whose field to get and set
       * @return the previous value
       */
      public int getAndIncrement(T obj) {
          int prev, next;
          do {
              prev = get(obj);
              next = prev + 1;
          } while (!compareAndSet(obj, prev, next));
          return prev;
      }
  
      /**
       * Atomically decrements by one the current value of the field of the
       * given object managed by this updater.
       *
       * @param obj An object whose field to get and set
       * @return the previous value
       */
      public int getAndDecrement(T obj) {
          int prev, next;
          do {
              prev = get(obj);
              next = prev - 1;
          } while (!compareAndSet(obj, prev, next));
          return prev;
      }
  
      /**
       * Atomically adds the given value to the current value of the field of
       * the given object managed by this updater.
       *
       * @param obj An object whose field to get and set
       * @param delta the value to add
       * @return the previous value
       */
      public int getAndAdd(T obj, int delta) {
          int prev, next;
          do {
              prev = get(obj);
              next = prev + delta;
          } while (!compareAndSet(obj, prev, next));
          return prev;
      }
  
      /**
       * Atomically increments by one the current value of the field of the
       * given object managed by this updater.
       *
       * @param obj An object whose field to get and set
       * @return the updated value
       */
      public int incrementAndGet(T obj) {
          int prev, next;
          do {
              prev = get(obj);
              next = prev + 1;
          } while (!compareAndSet(obj, prev, next));
          return next;
      }
  
      /**
       * Atomically decrements by one the current value of the field of the
       * given object managed by this updater.
       *
       * @param obj An object whose field to get and set
       * @return the updated value
       */
      public int decrementAndGet(T obj) {
          int prev, next;
          do {
              prev = get(obj);
              next = prev - 1;
          } while (!compareAndSet(obj, prev, next));
          return next;
      }
  
      /**
       * Atomically adds the given value to the current value of the field of
       * the given object managed by this updater.
       *
       * @param obj An object whose field to get and set
       * @param delta the value to add
       * @return the updated value
       */
      public int addAndGet(T obj, int delta) {
          int prev, next;
          do {
              prev = get(obj);
              next = prev + delta;
          } while (!compareAndSet(obj, prev, next));
          return next;
      }
  
      /**
       * Atomically updates the field of the given object managed by this updater
       * 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 obj An object whose field to get and set
       * @param updateFunction a side-effect-free function
       * @return the previous value
       * @since 1.8
       */
      public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
          int prev, next;
          do {
              prev = get(obj);
              next = updateFunction.applyAsInt(prev);
          } while (!compareAndSet(obj, prev, next));
          return prev;
      }
  
      /**
       * Atomically updates the field of the given object managed by this updater
       * 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 obj An object whose field to get and set
       * @param updateFunction a side-effect-free function
       * @return the updated value
       * @since 1.8
       */
      public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
          int prev, next;
          do {
              prev = get(obj);
              next = updateFunction.applyAsInt(prev);
          } while (!compareAndSet(obj, prev, next));
          return next;
      }
  
      /**
       * Atomically updates the field of the given object managed by this
       * updater 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 obj An object whose field to get and set
       * @param x the update value
       * @param accumulatorFunction a side-effect-free function of two arguments
       * @return the previous value
       * @since 1.8
       */
      public final int getAndAccumulate(T obj, int x,
                                        IntBinaryOperator accumulatorFunction) {
          int prev, next;
          do {
              prev = get(obj);
              next = accumulatorFunction.applyAsInt(prev, x);
          } while (!compareAndSet(obj, prev, next));
          return prev;
      }
  
      /**
       * Atomically updates the field of the given object managed by this
       * updater 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 obj An object whose field to get and set
       * @param x the update value
       * @param accumulatorFunction a side-effect-free function of two arguments
       * @return the updated value
       * @since 1.8
       */
      public final int accumulateAndGet(T obj, int x,
                                        IntBinaryOperator accumulatorFunction) {
          int prev, next;
          do {
              prev = get(obj);
              next = accumulatorFunction.applyAsInt(prev, x);
          } while (!compareAndSet(obj, prev, next));
          return next;
      }
  
      /**
       * Standard hotspot implementation using intrinsics.
       */
      private static final class AtomicIntegerFieldUpdaterImpl<T>
          extends AtomicIntegerFieldUpdater<T> {
          private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
          private final long offset;
          /**
           * if field is protected, the subclass constructing updater, else
           * the same as tclass
           */
          private final Class<?> cclass;
          /** class holding the field */
          private final Class<T> tclass;
  
          AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
                                        final String fieldName,
                                        final Class<?> caller) {
              final Field field;
              final int modifiers;
              try {
                  // BEGIN Android-changed: Skip privilege escalation which is a noop on Android.
                  /*
                  field = AccessController.doPrivileged(
                      new PrivilegedExceptionAction<Field>() {
                          public Field run() throws NoSuchFieldException {
                              return tclass.getDeclaredField(fieldName);
                          }
                      });
                  */
                  field = tclass.getDeclaredField(fieldName);
                  // END Android-changed: Skip privilege escalation which is a noop on Android.
                  modifiers = field.getModifiers();
                  sun.reflect.misc.ReflectUtil.ensureMemberAccess(
                      caller, tclass, null, modifiers);
                  // BEGIN Android-removed: Skip checkPackageAccess which is a noop on Android.
                  /*
                  ClassLoader cl = tclass.getClassLoader();
                  ClassLoader ccl = caller.getClassLoader();
                  if ((ccl != null) && (ccl != cl) &&
                      ((cl == null) || !isAncestor(cl, ccl))) {
                      sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                  }
                  */
                  // END Android-removed: Skip checkPackageAccess which is a noop on Android.
              // BEGIN Android-removed: Skip privilege escalation which is a noop on Android.
              /*
              } catch (PrivilegedActionException pae) {
                  throw new RuntimeException(pae.getException());
              */
              // END Android-removed: Skip privilege escalation which is a noop on Android.
              } catch (Exception ex) {
                  throw new RuntimeException(ex);
              }
  
              if (field.getType() != int.class)
                  throw new IllegalArgumentException("Must be integer type");
  
              if (!Modifier.isVolatile(modifiers))
                  throw new IllegalArgumentException("Must be volatile type");
  
              this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
              this.tclass = tclass;
              this.offset = U.objectFieldOffset(field);
          }
  
          // BEGIN Android-removed: isAncestor()'s only usage was removed above.
          /*
          /**
           * Returns true if the second classloader can be found in the first
           * classloader's delegation chain.
           * Equivalent to the inaccessible: first.isAncestor(second).
           *
          private static boolean isAncestor(ClassLoader first, ClassLoader second) {
              ClassLoader acl = first;
              do {
                  acl = acl.getParent();
                  if (second == acl) {
                      return true;
                  }
              } while (acl != null);
              return false;
          }
          */
          // END Android-removed: isAncestor()'s only usage was removed above.
  
          /**
           * Checks that target argument is instance of cclass.  On
           * failure, throws cause.
           */
          private final void accessCheck(T obj) {
              if (!cclass.isInstance(obj))
                  throwAccessCheckException(obj);
          }
  
          /**
           * Throws access exception if accessCheck failed due to
           * protected access, else ClassCastException.
           */
          private final void throwAccessCheckException(T obj) {
              if (cclass == tclass)
                  throw new ClassCastException();
              else
                  throw new RuntimeException(
                      new IllegalAccessException(
                          "Class " +
                          cclass.getName() +
                          " can not access a protected member of class " +
                          tclass.getName() +
                          " using an instance of " +
                          obj.getClass().getName()));
          }
  
          public final boolean compareAndSet(T obj, int expect, int update) {
              accessCheck(obj);
              return U.compareAndSwapInt(obj, offset, expect, update);
          }
  
          public final boolean weakCompareAndSet(T obj, int expect, int update) {
              accessCheck(obj);
              return U.compareAndSwapInt(obj, offset, expect, update);
          }
  
          public final void set(T obj, int newValue) {
              accessCheck(obj);
              U.putIntVolatile(obj, offset, newValue);
          }
  
          public final void lazySet(T obj, int newValue) {
              accessCheck(obj);
              U.putOrderedInt(obj, offset, newValue);
          }
  
          public final int get(T obj) {
              accessCheck(obj);
              return U.getIntVolatile(obj, offset);
          }
  
          public final int getAndSet(T obj, int newValue) {
              accessCheck(obj);
              return U.getAndSetInt(obj, offset, newValue);
          }
  
          public final int getAndAdd(T obj, int delta) {
              accessCheck(obj);
              return U.getAndAddInt(obj, offset, delta);
          }
  
          public final int getAndIncrement(T obj) {
              return getAndAdd(obj, 1);
          }
  
          public final int getAndDecrement(T obj) {
              return getAndAdd(obj, -1);
          }
  
          public final int incrementAndGet(T obj) {
              return getAndAdd(obj, 1) + 1;
          }
  
          public final int decrementAndGet(T obj) {
              return getAndAdd(obj, -1) - 1;
          }
  
          public final int addAndGet(T obj, int delta) {
              return getAndAdd(obj, delta) + delta;
          }
  
      }
  }
  