/*
 * 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.Objects;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import jdk.internal.misc.Unsafe;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import java.lang.invoke.VarHandle;

A reflection-based utility that enables atomic updates to designated 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.

Note that the guarantees of the 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 compareAndSet and set on the same updater.

Object arguments for parameters of type T that are not instances of the class passed to newUpdater will result in a ClassCastException being thrown.

Author:Doug Lea
Type parameters:
  • <T> – The type of the object holding the updatable field
Since:1.5
/** * 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. * * <p>Object arguments for parameters of type {@code T} that are not * instances of the class passed to {@link #newUpdater} will result in * a {@link ClassCastException} being thrown. * * @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.
Params:
  • tclass – the class of the objects holding the field
  • fieldName – the name of the field to be updated
Type parameters:
  • <U> – the type of instances of tclass
Throws:
  • IllegalArgumentException – if the field is not a volatile integer type
  • 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
Returns:the updater
/** * 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 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 == the expected value. This method is guaranteed to be atomic with respect to other calls to compareAndSet and set, but not necessarily with respect to other changes in the field.
Params:
  • obj – An object whose field to conditionally set
  • expect – the expected value
  • update – the new value
Returns:true if successful
/** * 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 */
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 == the expected value. This method is guaranteed to be atomic with respect to other calls to compareAndSet and set, but not necessarily with respect to other changes in the field.

May fail spuriously and does not provide ordering guarantees, so is only rarely an appropriate alternative to compareAndSet.

Params:
  • obj – An object whose field to conditionally set
  • expect – the expected value
  • update – the new value
Returns:true if successful
/** * 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 */
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 compareAndSet.
Params:
  • obj – An object whose field to set
  • newValue – the new value
/** * 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.
Params:
  • obj – An object whose field to set
  • newValue – the new value
Since:1.6
/** * 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);
Returns the current value held in the field of the given object managed by this updater.
Params:
  • obj – An object whose field to get
Returns:the current value
/** * Returns 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.
Params:
  • obj – An object whose field to get and set
  • newValue – the new value
Returns:the previous value
/** * 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.
Params:
  • obj – An object whose field to get and set
Returns:the previous value
/** * 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.
Params:
  • obj – An object whose field to get and set
Returns:the previous value
/** * 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.
Params:
  • obj – An object whose field to get and set
  • delta – the value to add
Returns:the previous value
/** * 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.
Params:
  • obj – An object whose field to get and set
Returns:the updated value
/** * 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.
Params:
  • obj – An object whose field to get and set
Returns:the updated value
/** * 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.
Params:
  • obj – An object whose field to get and set
  • delta – the value to add
Returns:the updated value
/** * 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 (with memory effects as specified by VarHandle.compareAndSet) 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.
Params:
  • obj – An object whose field to get and set
  • updateFunction – a side-effect-free function
Returns:the previous value
Since:1.8
/** * Atomically updates (with memory effects as specified by {@link * VarHandle#compareAndSet}) 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 (with memory effects as specified by VarHandle.compareAndSet) 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.
Params:
  • obj – An object whose field to get and set
  • updateFunction – a side-effect-free function
Returns:the updated value
Since:1.8
/** * Atomically updates (with memory effects as specified by {@link * VarHandle#compareAndSet}) 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 (with memory effects as specified by VarHandle.compareAndSet) 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.
Params:
  • obj – An object whose field to get and set
  • x – the update value
  • accumulatorFunction – a side-effect-free function of two arguments
Returns:the previous value
Since:1.8
/** * Atomically updates (with memory effects as specified by {@link * VarHandle#compareAndSet}) 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 (with memory effects as specified by VarHandle.compareAndSet) 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.
Params:
  • obj – An object whose field to get and set
  • x – the update value
  • accumulatorFunction – a side-effect-free function of two arguments
Returns:the updated value
Since:1.8
/** * Atomically updates (with memory effects as specified by {@link * VarHandle#compareAndSet}) 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.
/** * Standard hotspot implementation using intrinsics. */
private static final class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> { private static final Unsafe U = Unsafe.getUnsafe(); private final long offset;
if field is protected, the subclass constructing updater, else the same as tclass
/** * if field is protected, the subclass constructing updater, else * the same as tclass */
private final Class<?> cclass;
class holding the field
/** 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 { field = AccessController.doPrivileged( new PrivilegedExceptionAction<Field>() { public Field run() throws NoSuchFieldException { return tclass.getDeclaredField(fieldName); } }); modifiers = field.getModifiers(); sun.reflect.misc.ReflectUtil.ensureMemberAccess( caller, tclass, null, modifiers); ClassLoader cl = tclass.getClassLoader(); ClassLoader ccl = caller.getClassLoader(); if ((ccl != null) && (ccl != cl) && ((cl == null) || !isAncestor(cl, ccl))) { sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); } } catch (PrivilegedActionException pae) { throw new RuntimeException(pae.getException()); } 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"); // Access to protected field members is restricted to receivers only // of the accessing class, or one of its subclasses, and the // accessing class must in turn be a subclass (or package sibling) // of the protected member's defining class. // If the updater refers to a protected field of a declaring class // outside the current package, the receiver argument will be // narrowed to the type of the accessing class. this.cclass = (Modifier.isProtected(modifiers) && tclass.isAssignableFrom(caller) && !isSamePackage(tclass, caller)) ? caller : tclass; this.tclass = tclass; this.offset = U.objectFieldOffset(field); }
Returns true if the second classloader can be found in the first classloader's delegation chain. Equivalent to the inaccessible: first.isAncestor(second).
/** * 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; }
Returns true if the two classes have the same class loader and package qualifier
/** * Returns true if the two classes have the same class loader and * package qualifier */
private static boolean isSamePackage(Class<?> class1, Class<?> class2) { return class1.getClassLoader() == class2.getClassLoader() && Objects.equals(class1.getPackageName(), class2.getPackageName()); }
Checks that target argument is instance of cclass. On failure, throws cause.
/** * 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.
/** * 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.compareAndSetInt(obj, offset, expect, update); } public final boolean weakCompareAndSet(T obj, int expect, int update) { accessCheck(obj); return U.compareAndSetInt(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.putIntRelease(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; } } }