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 
  38 import java.lang.reflect.Field;
  39 import java.lang.reflect.Modifier;
  40 import java.security.AccessController;
  41 import java.security.PrivilegedActionException;
  42 import java.security.PrivilegedExceptionAction;
  43 import java.util.function.IntBinaryOperator;
  44 import java.util.function.IntUnaryOperator;
  45 import sun.reflect.CallerSensitive;
  46 import sun.reflect.Reflection;
  47 
  48 /**
  49  * A reflection-based utility that enables atomic updates to
  50  * designated {@code volatile int} fields of designated classes.
  51  * This class is designed for use in atomic data structures in which
  52  * several fields of the same node are independently subject to atomic
  53  * updates.
  54  *
  55  * <p>Note that the guarantees of the {@code compareAndSet}
  56  * method in this class are weaker than in other atomic classes.
  57  * Because this class cannot ensure that all uses of the field
  58  * are appropriate for purposes of atomic access, it can
  59  * guarantee atomicity only with respect to other invocations of
  60  * {@code compareAndSet} and {@code set} on the same updater.
  61  *
  62  * @since 1.5
  63  * @author Doug Lea
  64  * @param <T> The type of the object holding the updatable field
  65  */
  66 public abstract class AtomicIntegerFieldUpdater<T> {
  67     /**
  68      * Creates and returns an updater for objects with the given field.
  69      * The Class argument is needed to check that reflective types and
  70      * generic types match.
  71      *
  72      * @param tclass the class of the objects holding the field
  73      * @param fieldName the name of the field to be updated
  74      * @param <U> the type of instances of tclass
  75      * @return the updater
  76      * @throws IllegalArgumentException if the field is not a
  77      * volatile integer type
  78      * @throws RuntimeException with a nested reflection-based
  79      * exception if the class does not hold field or is the wrong type,
  80      * or the field is inaccessible to the caller according to Java language
  81      * access control
  82      */
  83     @CallerSensitive
  84     public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
  85                                                               String fieldName) {
  86         return new AtomicIntegerFieldUpdaterImpl<U>
  87             (tclass, fieldName, Reflection.getCallerClass());
  88     }
  89 
  90     /**
  91      * Protected do-nothing constructor for use by subclasses.
  92      */
  93     protected AtomicIntegerFieldUpdater() {
  94     }
  95 
  96     /**
  97      * Atomically sets the field of the given object managed by this updater
  98      * to the given updated value if the current value {@code ==} the
  99      * expected value. This method is guaranteed to be atomic with respect to
 100      * other calls to {@code compareAndSet} and {@code set}, but not
 101      * necessarily with respect to other changes in the field.
 102      *
 103      * @param obj An object whose field to conditionally set
 104      * @param expect the expected value
 105      * @param update the new value
 106      * @return {@code true} if successful
 107      * @throws ClassCastException if {@code obj} is not an instance
 108      * of the class possessing the field established in the constructor
 109      */
 110     public abstract boolean compareAndSet(T obj, int expect, int update);
 111 
 112     /**
 113      * Atomically sets the field of the given object managed by this updater
 114      * to the given updated value if the current value {@code ==} the
 115      * expected value. This method is guaranteed to be atomic with respect to
 116      * other calls to {@code compareAndSet} and {@code set}, but not
 117      * necessarily with respect to other changes in the field.
 118      *
 119      * <p><a href="package-summary.html#weakCompareAndSet">May fail
 120      * spuriously and does not provide ordering guarantees</a>, so is
 121      * only rarely an appropriate alternative to {@code compareAndSet}.
 122      *
 123      * @param obj An object whose field to conditionally set
 124      * @param expect the expected value
 125      * @param update the new value
 126      * @return {@code true} if successful
 127      * @throws ClassCastException if {@code obj} is not an instance
 128      * of the class possessing the field established in the constructor
 129      */
 130     public abstract boolean weakCompareAndSet(T obj, int expect, int update);
 131 
 132     /**
 133      * Sets the field of the given object managed by this updater to the
 134      * given updated value. This operation is guaranteed to act as a volatile
 135      * store with respect to subsequent invocations of {@code compareAndSet}.
 136      *
 137      * @param obj An object whose field to set
 138      * @param newValue the new value
 139      */
 140     public abstract void set(T obj, int newValue);
 141 
 142     /**
 143      * Eventually sets the field of the given object managed by this
 144      * updater to the given updated value.
 145      *
 146      * @param obj An object whose field to set
 147      * @param newValue the new value
 148      * @since 1.6
 149      */
 150     public abstract void lazySet(T obj, int newValue);
 151 
 152     /**
 153      * Gets the current value held in the field of the given object managed
 154      * by this updater.
 155      *
 156      * @param obj An object whose field to get
 157      * @return the current value
 158      */
 159     public abstract int get(T obj);
 160 
 161     /**
 162      * Atomically sets the field of the given object managed by this updater
 163      * to the given value and returns the old value.
 164      *
 165      * @param obj An object whose field to get and set
 166      * @param newValue the new value
 167      * @return the previous value
 168      */
 169     public int getAndSet(T obj, int newValue) {
 170         int prev;
 171         do {
 172             prev = get(obj);
 173         } while (!compareAndSet(obj, prev, newValue));
 174         return prev;
 175     }
 176 
 177     /**
 178      * Atomically increments by one the current value of the field of the
 179      * given object managed by this updater.
 180      *
 181      * @param obj An object whose field to get and set
 182      * @return the previous value
 183      */
 184     public int getAndIncrement(T obj) {
 185         int prev, next;
 186         do {
 187             prev = get(obj);
 188             next = prev + 1;
 189         } while (!compareAndSet(obj, prev, next));
 190         return prev;
 191     }
 192 
 193     /**
 194      * Atomically decrements by one the current value of the field of the
 195      * given object managed by this updater.
 196      *
 197      * @param obj An object whose field to get and set
 198      * @return the previous value
 199      */
 200     public int getAndDecrement(T obj) {
 201         int prev, next;
 202         do {
 203             prev = get(obj);
 204             next = prev - 1;
 205         } while (!compareAndSet(obj, prev, next));
 206         return prev;
 207     }
 208 
 209     /**
 210      * Atomically adds the given value to the current value of the field of
 211      * the given object managed by this updater.
 212      *
 213      * @param obj An object whose field to get and set
 214      * @param delta the value to add
 215      * @return the previous value
 216      */
 217     public int getAndAdd(T obj, int delta) {
 218         int prev, next;
 219         do {
 220             prev = get(obj);
 221             next = prev + delta;
 222         } while (!compareAndSet(obj, prev, next));
 223         return prev;
 224     }
 225 
 226     /**
 227      * Atomically increments by one the current value of the field of the
 228      * given object managed by this updater.
 229      *
 230      * @param obj An object whose field to get and set
 231      * @return the updated value
 232      */
 233     public int incrementAndGet(T obj) {
 234         int prev, next;
 235         do {
 236             prev = get(obj);
 237             next = prev + 1;
 238         } while (!compareAndSet(obj, prev, next));
 239         return next;
 240     }
 241 
 242     /**
 243      * Atomically decrements by one the current value of the field of the
 244      * given object managed by this updater.
 245      *
 246      * @param obj An object whose field to get and set
 247      * @return the updated value
 248      */
 249     public int decrementAndGet(T obj) {
 250         int prev, next;
 251         do {
 252             prev = get(obj);
 253             next = prev - 1;
 254         } while (!compareAndSet(obj, prev, next));
 255         return next;
 256     }
 257 
 258     /**
 259      * Atomically adds the given value to the current value of the field of
 260      * the given object managed by this updater.
 261      *
 262      * @param obj An object whose field to get and set
 263      * @param delta the value to add
 264      * @return the updated value
 265      */
 266     public int addAndGet(T obj, int delta) {
 267         int prev, next;
 268         do {
 269             prev = get(obj);
 270             next = prev + delta;
 271         } while (!compareAndSet(obj, prev, next));
 272         return next;
 273     }
 274 
 275     /**
 276      * Atomically updates the field of the given object managed by this updater
 277      * with the results of applying the given function, returning the previous
 278      * value. The function should be side-effect-free, since it may be
 279      * re-applied when attempted updates fail due to contention among threads.
 280      *
 281      * @param obj An object whose field to get and set
 282      * @param updateFunction a side-effect-free function
 283      * @return the previous value
 284      * @since 1.8
 285      */
 286     public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
 287         int prev, next;
 288         do {
 289             prev = get(obj);
 290             next = updateFunction.applyAsInt(prev);
 291         } while (!compareAndSet(obj, prev, next));
 292         return prev;
 293     }
 294 
 295     /**
 296      * Atomically updates the field of the given object managed by this updater
 297      * with the results of applying the given function, returning the updated
 298      * value. The function should be side-effect-free, since it may be
 299      * re-applied when attempted updates fail due to contention among threads.
 300      *
 301      * @param obj An object whose field to get and set
 302      * @param updateFunction a side-effect-free function
 303      * @return the updated value
 304      * @since 1.8
 305      */
 306     public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
 307         int prev, next;
 308         do {
 309             prev = get(obj);
 310             next = updateFunction.applyAsInt(prev);
 311         } while (!compareAndSet(obj, prev, next));
 312         return next;
 313     }
 314 
 315     /**
 316      * Atomically updates the field of the given object managed by this
 317      * updater with the results of applying the given function to the
 318      * current and given values, returning the previous value. The
 319      * function should be side-effect-free, since it may be re-applied
 320      * when attempted updates fail due to contention among threads.  The
 321      * function is applied with the current value as its first argument,
 322      * and the given update as the second argument.
 323      *
 324      * @param obj An object whose field to get and set
 325      * @param x the update value
 326      * @param accumulatorFunction a side-effect-free function of two arguments
 327      * @return the previous value
 328      * @since 1.8
 329      */
 330     public final int getAndAccumulate(T obj, int x,
 331                                       IntBinaryOperator accumulatorFunction) {
 332         int prev, next;
 333         do {
 334             prev = get(obj);
 335             next = accumulatorFunction.applyAsInt(prev, x);
 336         } while (!compareAndSet(obj, prev, next));
 337         return prev;
 338     }
 339 
 340     /**
 341      * Atomically updates the field of the given object managed by this
 342      * updater with the results of applying the given function to the
 343      * current and given values, returning the updated value. The
 344      * function should be side-effect-free, since it may be re-applied
 345      * when attempted updates fail due to contention among threads.  The
 346      * function is applied with the current value as its first argument,
 347      * and the given update as the second argument.
 348      *
 349      * @param obj An object whose field to get and set
 350      * @param x the update value
 351      * @param accumulatorFunction a side-effect-free function of two arguments
 352      * @return the updated value
 353      * @since 1.8
 354      */
 355     public final int accumulateAndGet(T obj, int x,
 356                                       IntBinaryOperator accumulatorFunction) {
 357         int prev, next;
 358         do {
 359             prev = get(obj);
 360             next = accumulatorFunction.applyAsInt(prev, x);
 361         } while (!compareAndSet(obj, prev, next));
 362         return next;
 363     }
 364 
 365     /**
 366      * Standard hotspot implementation using intrinsics.
 367      */
 368     private static class AtomicIntegerFieldUpdaterImpl<T>
 369             extends AtomicIntegerFieldUpdater<T> {
 370         private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
 371         private final long offset;
 372         private final Class<T> tclass;
 373         private final Class<?> cclass;
 374 
 375         AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
 376                                       final String fieldName,
 377                                       final Class<?> caller) {
 378             final Field field;
 379             final int modifiers;
 380             try {
 381                 field = AccessController.doPrivileged(
 382                     new PrivilegedExceptionAction<Field>() {
 383                         public Field run() throws NoSuchFieldException {
 384                             return tclass.getDeclaredField(fieldName);
 385                         }
 386                     });
 387                 modifiers = field.getModifiers();
 388                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
 389                     caller, tclass, null, modifiers);
 390                 ClassLoader cl = tclass.getClassLoader();
 391                 ClassLoader ccl = caller.getClassLoader();
 392                 if ((ccl != null) && (ccl != cl) &&
 393                     ((cl == null) || !isAncestor(cl, ccl))) {
 394                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
 395                 }
 396             } catch (PrivilegedActionException pae) {
 397                 throw new RuntimeException(pae.getException());
 398             } catch (Exception ex) {
 399                 throw new RuntimeException(ex);
 400             }
 401 
 402             Class<?> fieldt = field.getType();
 403             if (fieldt != int.class)
 404                 throw new IllegalArgumentException("Must be integer type");
 405 
 406             if (!Modifier.isVolatile(modifiers))
 407                 throw new IllegalArgumentException("Must be volatile type");
 408 
 409             this.cclass = (Modifier.isProtected(modifiers) &&
 410                            caller != tclass) ? caller : null;
 411             this.tclass = tclass;
 412             offset = U.objectFieldOffset(field);
 413         }
 414 
 415         /**
 416          * Returns true if the second classloader can be found in the first
 417          * classloader's delegation chain.
 418          * Equivalent to the inaccessible: first.isAncestor(second).
 419          */
 420         private static boolean isAncestor(ClassLoader first, ClassLoader second) {
 421             ClassLoader acl = first;
 422             do {
 423                 acl = acl.getParent();
 424                 if (second == acl) {
 425                     return true;
 426                 }
 427             } while (acl != null);
 428             return false;
 429         }
 430 
 431         private void fullCheck(T obj) {
 432             if (!tclass.isInstance(obj))
 433                 throw new ClassCastException();
 434             if (cclass != null)
 435                 ensureProtectedAccess(obj);
 436         }
 437 
 438         public boolean compareAndSet(T obj, int expect, int update) {
 439             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 440             return U.compareAndSwapInt(obj, offset, expect, update);
 441         }
 442 
 443         public boolean weakCompareAndSet(T obj, int expect, int update) {
 444             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 445             return U.compareAndSwapInt(obj, offset, expect, update);
 446         }
 447 
 448         public void set(T obj, int newValue) {
 449             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 450             U.putIntVolatile(obj, offset, newValue);
 451         }
 452 
 453         public void lazySet(T obj, int newValue) {
 454             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 455             U.putOrderedInt(obj, offset, newValue);
 456         }
 457 
 458         public final int get(T obj) {
 459             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 460             return U.getIntVolatile(obj, offset);
 461         }
 462 
 463         public int getAndSet(T obj, int newValue) {
 464             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 465             return U.getAndSetInt(obj, offset, newValue);
 466         }
 467 
 468         public int getAndIncrement(T obj) {
 469             return getAndAdd(obj, 1);
 470         }
 471 
 472         public int getAndDecrement(T obj) {
 473             return getAndAdd(obj, -1);
 474         }
 475 
 476         public int getAndAdd(T obj, int delta) {
 477             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 478             return U.getAndAddInt(obj, offset, delta);
 479         }
 480 
 481         public int incrementAndGet(T obj) {
 482             return getAndAdd(obj, 1) + 1;
 483         }
 484 
 485         public int decrementAndGet(T obj) {
 486             return getAndAdd(obj, -1) - 1;
 487         }
 488 
 489         public int addAndGet(T obj, int delta) {
 490             return getAndAdd(obj, delta) + delta;
 491         }
 492 
 493         private void ensureProtectedAccess(T obj) {
 494             if (cclass.isInstance(obj)) {
 495                 return;
 496             }
 497             throw new RuntimeException(
 498                 new IllegalAccessException("Class " +
 499                     cclass.getName() +
 500                     " can not access a protected member of class " +
 501                     tclass.getName() +
 502                     " using an instance of " +
 503                     obj.getClass().getName()
 504                 )
 505             );
 506         }
 507     }
 508 }