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.LongBinaryOperator;
  44 import java.util.function.LongUnaryOperator;
  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 long} 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 AtomicLongFieldUpdater<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 long 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> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
  85                                                            String fieldName) {
  86         Class<?> caller = Reflection.getCallerClass();
  87         if (AtomicLong.VM_SUPPORTS_LONG_CAS)
  88             return new CASUpdater<U>(tclass, fieldName, caller);
  89         else
  90             return new LockedUpdater<U>(tclass, fieldName, caller);
  91     }
  92 
  93     /**
  94      * Protected do-nothing constructor for use by subclasses.
  95      */
  96     protected AtomicLongFieldUpdater() {
  97     }
  98 
  99     /**
 100      * Atomically sets the field of the given object managed by this updater
 101      * to the given updated value if the current value {@code ==} the
 102      * expected value. This method is guaranteed to be atomic with respect to
 103      * other calls to {@code compareAndSet} and {@code set}, but not
 104      * necessarily with respect to other changes in the field.
 105      *
 106      * @param obj An object whose field to conditionally set
 107      * @param expect the expected value
 108      * @param update the new value
 109      * @return {@code true} if successful
 110      * @throws ClassCastException if {@code obj} is not an instance
 111      * of the class possessing the field established in the constructor
 112      */
 113     public abstract boolean compareAndSet(T obj, long expect, long update);
 114 
 115     /**
 116      * Atomically sets the field of the given object managed by this updater
 117      * to the given updated value if the current value {@code ==} the
 118      * expected value. This method is guaranteed to be atomic with respect to
 119      * other calls to {@code compareAndSet} and {@code set}, but not
 120      * necessarily with respect to other changes in the field.
 121      *
 122      * <p><a href="package-summary.html#weakCompareAndSet">May fail
 123      * spuriously and does not provide ordering guarantees</a>, so is
 124      * only rarely an appropriate alternative to {@code compareAndSet}.
 125      *
 126      * @param obj An object whose field to conditionally set
 127      * @param expect the expected value
 128      * @param update the new value
 129      * @return {@code true} if successful
 130      * @throws ClassCastException if {@code obj} is not an instance
 131      * of the class possessing the field established in the constructor
 132      */
 133     public abstract boolean weakCompareAndSet(T obj, long expect, long update);
 134 
 135     /**
 136      * Sets the field of the given object managed by this updater to the
 137      * given updated value. This operation is guaranteed to act as a volatile
 138      * store with respect to subsequent invocations of {@code compareAndSet}.
 139      *
 140      * @param obj An object whose field to set
 141      * @param newValue the new value
 142      */
 143     public abstract void set(T obj, long newValue);
 144 
 145     /**
 146      * Eventually sets the field of the given object managed by this
 147      * updater to the given updated value.
 148      *
 149      * @param obj An object whose field to set
 150      * @param newValue the new value
 151      * @since 1.6
 152      */
 153     public abstract void lazySet(T obj, long newValue);
 154 
 155     /**
 156      * Gets the current value held in the field of the given object managed
 157      * by this updater.
 158      *
 159      * @param obj An object whose field to get
 160      * @return the current value
 161      */
 162     public abstract long get(T obj);
 163 
 164     /**
 165      * Atomically sets the field of the given object managed by this updater
 166      * to the given value and returns the old value.
 167      *
 168      * @param obj An object whose field to get and set
 169      * @param newValue the new value
 170      * @return the previous value
 171      */
 172     public long getAndSet(T obj, long newValue) {
 173         long prev;
 174         do {
 175             prev = get(obj);
 176         } while (!compareAndSet(obj, prev, newValue));
 177         return prev;
 178     }
 179 
 180     /**
 181      * Atomically increments by one the current value of the field of the
 182      * given object managed by this updater.
 183      *
 184      * @param obj An object whose field to get and set
 185      * @return the previous value
 186      */
 187     public long getAndIncrement(T obj) {
 188         long prev, next;
 189         do {
 190             prev = get(obj);
 191             next = prev + 1;
 192         } while (!compareAndSet(obj, prev, next));
 193         return prev;
 194     }
 195 
 196     /**
 197      * Atomically decrements by one the current value of the field of the
 198      * given object managed by this updater.
 199      *
 200      * @param obj An object whose field to get and set
 201      * @return the previous value
 202      */
 203     public long getAndDecrement(T obj) {
 204         long prev, next;
 205         do {
 206             prev = get(obj);
 207             next = prev - 1;
 208         } while (!compareAndSet(obj, prev, next));
 209         return prev;
 210     }
 211 
 212     /**
 213      * Atomically adds the given value to the current value of the field of
 214      * the given object managed by this updater.
 215      *
 216      * @param obj An object whose field to get and set
 217      * @param delta the value to add
 218      * @return the previous value
 219      */
 220     public long getAndAdd(T obj, long delta) {
 221         long prev, next;
 222         do {
 223             prev = get(obj);
 224             next = prev + delta;
 225         } while (!compareAndSet(obj, prev, next));
 226         return prev;
 227     }
 228 
 229     /**
 230      * Atomically increments by one the current value of the field of the
 231      * given object managed by this updater.
 232      *
 233      * @param obj An object whose field to get and set
 234      * @return the updated value
 235      */
 236     public long incrementAndGet(T obj) {
 237         long prev, next;
 238         do {
 239             prev = get(obj);
 240             next = prev + 1;
 241         } while (!compareAndSet(obj, prev, next));
 242         return next;
 243     }
 244 
 245     /**
 246      * Atomically decrements by one the current value of the field of the
 247      * given object managed by this updater.
 248      *
 249      * @param obj An object whose field to get and set
 250      * @return the updated value
 251      */
 252     public long decrementAndGet(T obj) {
 253         long prev, next;
 254         do {
 255             prev = get(obj);
 256             next = prev - 1;
 257         } while (!compareAndSet(obj, prev, next));
 258         return next;
 259     }
 260 
 261     /**
 262      * Atomically adds the given value to the current value of the field of
 263      * the given object managed by this updater.
 264      *
 265      * @param obj An object whose field to get and set
 266      * @param delta the value to add
 267      * @return the updated value
 268      */
 269     public long addAndGet(T obj, long delta) {
 270         long prev, next;
 271         do {
 272             prev = get(obj);
 273             next = prev + delta;
 274         } while (!compareAndSet(obj, prev, next));
 275         return next;
 276     }
 277 
 278     /**
 279      * Atomically updates the field of the given object managed by this updater
 280      * with the results of applying the given function, returning the previous
 281      * value. The function should be side-effect-free, since it may be
 282      * re-applied when attempted updates fail due to contention among threads.
 283      *
 284      * @param obj An object whose field to get and set
 285      * @param updateFunction a side-effect-free function
 286      * @return the previous value
 287      * @since 1.8
 288      */
 289     public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
 290         long prev, next;
 291         do {
 292             prev = get(obj);
 293             next = updateFunction.applyAsLong(prev);
 294         } while (!compareAndSet(obj, prev, next));
 295         return prev;
 296     }
 297 
 298     /**
 299      * Atomically updates the field of the given object managed by this updater
 300      * with the results of applying the given function, returning the updated
 301      * value. The function should be side-effect-free, since it may be
 302      * re-applied when attempted updates fail due to contention among threads.
 303      *
 304      * @param obj An object whose field to get and set
 305      * @param updateFunction a side-effect-free function
 306      * @return the updated value
 307      * @since 1.8
 308      */
 309     public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
 310         long prev, next;
 311         do {
 312             prev = get(obj);
 313             next = updateFunction.applyAsLong(prev);
 314         } while (!compareAndSet(obj, prev, next));
 315         return next;
 316     }
 317 
 318     /**
 319      * Atomically updates the field of the given object managed by this
 320      * updater with the results of applying the given function to the
 321      * current and given values, returning the previous value. The
 322      * function should be side-effect-free, since it may be re-applied
 323      * when attempted updates fail due to contention among threads.  The
 324      * function is applied with the current value as its first argument,
 325      * and the given update as the second argument.
 326      *
 327      * @param obj An object whose field to get and set
 328      * @param x the update value
 329      * @param accumulatorFunction a side-effect-free function of two arguments
 330      * @return the previous value
 331      * @since 1.8
 332      */
 333     public final long getAndAccumulate(T obj, long x,
 334                                        LongBinaryOperator accumulatorFunction) {
 335         long prev, next;
 336         do {
 337             prev = get(obj);
 338             next = accumulatorFunction.applyAsLong(prev, x);
 339         } while (!compareAndSet(obj, prev, next));
 340         return prev;
 341     }
 342 
 343     /**
 344      * Atomically updates the field of the given object managed by this
 345      * updater with the results of applying the given function to the
 346      * current and given values, returning the updated value. The
 347      * function should be side-effect-free, since it may be re-applied
 348      * when attempted updates fail due to contention among threads.  The
 349      * function is applied with the current value as its first argument,
 350      * and the given update as the second argument.
 351      *
 352      * @param obj An object whose field to get and set
 353      * @param x the update value
 354      * @param accumulatorFunction a side-effect-free function of two arguments
 355      * @return the updated value
 356      * @since 1.8
 357      */
 358     public final long accumulateAndGet(T obj, long x,
 359                                        LongBinaryOperator accumulatorFunction) {
 360         long prev, next;
 361         do {
 362             prev = get(obj);
 363             next = accumulatorFunction.applyAsLong(prev, x);
 364         } while (!compareAndSet(obj, prev, next));
 365         return next;
 366     }
 367 
 368     private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
 369         private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
 370         private final long offset;
 371         private final Class<T> tclass;
 372         private final Class<?> cclass;
 373 
 374         CASUpdater(final Class<T> tclass, final String fieldName,
 375                    final Class<?> caller) {
 376             final Field field;
 377             final int modifiers;
 378             try {
 379                 field = AccessController.doPrivileged(
 380                     new PrivilegedExceptionAction<Field>() {
 381                         public Field run() throws NoSuchFieldException {
 382                             return tclass.getDeclaredField(fieldName);
 383                         }
 384                     });
 385                 modifiers = field.getModifiers();
 386                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
 387                     caller, tclass, null, modifiers);
 388                 ClassLoader cl = tclass.getClassLoader();
 389                 ClassLoader ccl = caller.getClassLoader();
 390                 if ((ccl != null) && (ccl != cl) &&
 391                     ((cl == null) || !isAncestor(cl, ccl))) {
 392                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
 393                 }
 394             } catch (PrivilegedActionException pae) {
 395                 throw new RuntimeException(pae.getException());
 396             } catch (Exception ex) {
 397                 throw new RuntimeException(ex);
 398             }
 399 
 400             Class<?> fieldt = field.getType();
 401             if (fieldt != long.class)
 402                 throw new IllegalArgumentException("Must be long type");
 403 
 404             if (!Modifier.isVolatile(modifiers))
 405                 throw new IllegalArgumentException("Must be volatile type");
 406 
 407             this.cclass = (Modifier.isProtected(modifiers) &&
 408                            caller != tclass) ? caller : null;
 409             this.tclass = tclass;
 410             offset = U.objectFieldOffset(field);
 411         }
 412 
 413         private void fullCheck(T obj) {
 414             if (!tclass.isInstance(obj))
 415                 throw new ClassCastException();
 416             if (cclass != null)
 417                 ensureProtectedAccess(obj);
 418         }
 419 
 420         public boolean compareAndSet(T obj, long expect, long update) {
 421             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 422             return U.compareAndSwapLong(obj, offset, expect, update);
 423         }
 424 
 425         public boolean weakCompareAndSet(T obj, long expect, long update) {
 426             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 427             return U.compareAndSwapLong(obj, offset, expect, update);
 428         }
 429 
 430         public void set(T obj, long newValue) {
 431             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 432             U.putLongVolatile(obj, offset, newValue);
 433         }
 434 
 435         public void lazySet(T obj, long newValue) {
 436             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 437             U.putOrderedLong(obj, offset, newValue);
 438         }
 439 
 440         public long get(T obj) {
 441             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 442             return U.getLongVolatile(obj, offset);
 443         }
 444 
 445         public long getAndSet(T obj, long newValue) {
 446             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 447             return U.getAndSetLong(obj, offset, newValue);
 448         }
 449 
 450         public long getAndIncrement(T obj) {
 451             return getAndAdd(obj, 1);
 452         }
 453 
 454         public long getAndDecrement(T obj) {
 455             return getAndAdd(obj, -1);
 456         }
 457 
 458         public long getAndAdd(T obj, long delta) {
 459             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 460             return U.getAndAddLong(obj, offset, delta);
 461         }
 462 
 463         public long incrementAndGet(T obj) {
 464             return getAndAdd(obj, 1) + 1;
 465         }
 466 
 467         public long decrementAndGet(T obj) {
 468             return getAndAdd(obj, -1) - 1;
 469         }
 470 
 471         public long addAndGet(T obj, long delta) {
 472             return getAndAdd(obj, delta) + delta;
 473         }
 474 
 475         private void ensureProtectedAccess(T obj) {
 476             if (cclass.isInstance(obj)) {
 477                 return;
 478             }
 479             throw new RuntimeException(
 480                 new IllegalAccessException("Class " +
 481                     cclass.getName() +
 482                     " can not access a protected member of class " +
 483                     tclass.getName() +
 484                     " using an instance of " +
 485                     obj.getClass().getName()
 486                 )
 487             );
 488         }
 489     }
 490 
 491 
 492     private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
 493         private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
 494         private final long offset;
 495         private final Class<T> tclass;
 496         private final Class<?> cclass;
 497 
 498         LockedUpdater(final Class<T> tclass, final String fieldName,
 499                       final Class<?> caller) {
 500             Field field = null;
 501             int modifiers = 0;
 502             try {
 503                 field = AccessController.doPrivileged(
 504                     new PrivilegedExceptionAction<Field>() {
 505                         public Field run() throws NoSuchFieldException {
 506                             return tclass.getDeclaredField(fieldName);
 507                         }
 508                     });
 509                 modifiers = field.getModifiers();
 510                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
 511                     caller, tclass, null, modifiers);
 512                 ClassLoader cl = tclass.getClassLoader();
 513                 ClassLoader ccl = caller.getClassLoader();
 514                 if ((ccl != null) && (ccl != cl) &&
 515                     ((cl == null) || !isAncestor(cl, ccl))) {
 516                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
 517                 }
 518             } catch (PrivilegedActionException pae) {
 519                 throw new RuntimeException(pae.getException());
 520             } catch (Exception ex) {
 521                 throw new RuntimeException(ex);
 522             }
 523 
 524             Class<?> fieldt = field.getType();
 525             if (fieldt != long.class)
 526                 throw new IllegalArgumentException("Must be long type");
 527 
 528             if (!Modifier.isVolatile(modifiers))
 529                 throw new IllegalArgumentException("Must be volatile type");
 530 
 531             this.cclass = (Modifier.isProtected(modifiers) &&
 532                            caller != tclass) ? caller : null;
 533             this.tclass = tclass;
 534             offset = U.objectFieldOffset(field);
 535         }
 536 
 537         private void fullCheck(T obj) {
 538             if (!tclass.isInstance(obj))
 539                 throw new ClassCastException();
 540             if (cclass != null)
 541                 ensureProtectedAccess(obj);
 542         }
 543 
 544         public boolean compareAndSet(T obj, long expect, long update) {
 545             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 546             synchronized (this) {
 547                 long v = U.getLong(obj, offset);
 548                 if (v != expect)
 549                     return false;
 550                 U.putLong(obj, offset, update);
 551                 return true;
 552             }
 553         }
 554 
 555         public boolean weakCompareAndSet(T obj, long expect, long update) {
 556             return compareAndSet(obj, expect, update);
 557         }
 558 
 559         public void set(T obj, long newValue) {
 560             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 561             synchronized (this) {
 562                 U.putLong(obj, offset, newValue);
 563             }
 564         }
 565 
 566         public void lazySet(T obj, long newValue) {
 567             set(obj, newValue);
 568         }
 569 
 570         public long get(T obj) {
 571             if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
 572             synchronized (this) {
 573                 return U.getLong(obj, offset);
 574             }
 575         }
 576 
 577         private void ensureProtectedAccess(T obj) {
 578             if (cclass.isInstance(obj)) {
 579                 return;
 580             }
 581             throw new RuntimeException(
 582                 new IllegalAccessException("Class " +
 583                     cclass.getName() +
 584                     " can not access a protected member of class " +
 585                     tclass.getName() +
 586                     " using an instance of " +
 587                     obj.getClass().getName()
 588                 )
 589             );
 590         }
 591     }
 592 
 593     /**
 594      * Returns true if the second classloader can be found in the first
 595      * classloader's delegation chain.
 596      * Equivalent to the inaccessible: first.isAncestor(second).
 597      */
 598     static boolean isAncestor(ClassLoader first, ClassLoader second) {
 599         ClassLoader acl = first;
 600         do {
 601             acl = acl.getParent();
 602             if (second == acl) {
 603                 return true;
 604             }
 605         } while (acl != null);
 606         return false;
 607     }
 608 }