1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 */ 6 7 package java.util.concurrent.atomic; 8 9 import dalvik.system.VMStack; // android-added 10 import java.lang.reflect.Field; 11 import java.lang.reflect.Modifier; 12 import java.security.AccessController; 13 import java.security.PrivilegedActionException; 14 import java.security.PrivilegedExceptionAction; 15 import java.util.function.LongBinaryOperator; 16 import java.util.function.LongUnaryOperator; 17 import sun.reflect.CallerSensitive; 18 import sun.reflect.Reflection; 19 20 /** 21 * A reflection-based utility that enables atomic updates to 22 * designated {@code volatile long} fields of designated classes. 23 * This class is designed for use in atomic data structures in which 24 * several fields of the same node are independently subject to atomic 25 * updates. 26 * 27 * <p>Note that the guarantees of the {@code compareAndSet} 28 * method in this class are weaker than in other atomic classes. 29 * Because this class cannot ensure that all uses of the field 30 * are appropriate for purposes of atomic access, it can 31 * guarantee atomicity only with respect to other invocations of 32 * {@code compareAndSet} and {@code set} on the same updater. 33 * 34 * @since 1.5 35 * @author Doug Lea 36 * @param <T> The type of the object holding the updatable field 37 */ 38 public abstract class AtomicLongFieldUpdater<T> { 39 /** 40 * Creates and returns an updater for objects with the given field. 41 * The Class argument is needed to check that reflective types and 42 * generic types match. 43 * 44 * @param tclass the class of the objects holding the field 45 * @param fieldName the name of the field to be updated 46 * @param <U> the type of instances of tclass 47 * @return the updater 48 * @throws IllegalArgumentException if the field is not a 49 * volatile long type 50 * @throws RuntimeException with a nested reflection-based 51 * exception if the class does not hold field or is the wrong type, 52 * or the field is inaccessible to the caller according to Java language 53 * access control 54 */ 55 @CallerSensitive newUpdater(Class<U> tclass, String fieldName)56 public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, 57 String fieldName) { 58 Class<?> caller = VMStack.getStackClass1(); // android-changed 59 if (AtomicLong.VM_SUPPORTS_LONG_CAS) 60 return new CASUpdater<U>(tclass, fieldName, caller); 61 else 62 return new LockedUpdater<U>(tclass, fieldName, caller); 63 } 64 65 /** 66 * Protected do-nothing constructor for use by subclasses. 67 */ AtomicLongFieldUpdater()68 protected AtomicLongFieldUpdater() { 69 } 70 71 /** 72 * Atomically sets the field of the given object managed by this updater 73 * to the given updated value if the current value {@code ==} the 74 * expected value. This method is guaranteed to be atomic with respect to 75 * other calls to {@code compareAndSet} and {@code set}, but not 76 * necessarily with respect to other changes in the field. 77 * 78 * @param obj An object whose field to conditionally set 79 * @param expect the expected value 80 * @param update the new value 81 * @return {@code true} if successful 82 * @throws ClassCastException if {@code obj} is not an instance 83 * of the class possessing the field established in the constructor 84 */ compareAndSet(T obj, long expect, long update)85 public abstract boolean compareAndSet(T obj, long expect, long update); 86 87 /** 88 * Atomically sets the field of the given object managed by this updater 89 * to the given updated value if the current value {@code ==} the 90 * expected value. This method is guaranteed to be atomic with respect to 91 * other calls to {@code compareAndSet} and {@code set}, but not 92 * necessarily with respect to other changes in the field. 93 * 94 * <p><a href="package-summary.html#weakCompareAndSet">May fail 95 * spuriously and does not provide ordering guarantees</a>, so is 96 * only rarely an appropriate alternative to {@code compareAndSet}. 97 * 98 * @param obj An object whose field to conditionally set 99 * @param expect the expected value 100 * @param update the new value 101 * @return {@code true} if successful 102 * @throws ClassCastException if {@code obj} is not an instance 103 * of the class possessing the field established in the constructor 104 */ weakCompareAndSet(T obj, long expect, long update)105 public abstract boolean weakCompareAndSet(T obj, long expect, long update); 106 107 /** 108 * Sets the field of the given object managed by this updater to the 109 * given updated value. This operation is guaranteed to act as a volatile 110 * store with respect to subsequent invocations of {@code compareAndSet}. 111 * 112 * @param obj An object whose field to set 113 * @param newValue the new value 114 */ set(T obj, long newValue)115 public abstract void set(T obj, long newValue); 116 117 /** 118 * Eventually sets the field of the given object managed by this 119 * updater to the given updated value. 120 * 121 * @param obj An object whose field to set 122 * @param newValue the new value 123 * @since 1.6 124 */ lazySet(T obj, long newValue)125 public abstract void lazySet(T obj, long newValue); 126 127 /** 128 * Gets the current value held in the field of the given object managed 129 * by this updater. 130 * 131 * @param obj An object whose field to get 132 * @return the current value 133 */ get(T obj)134 public abstract long get(T obj); 135 136 /** 137 * Atomically sets the field of the given object managed by this updater 138 * to the given value and returns the old value. 139 * 140 * @param obj An object whose field to get and set 141 * @param newValue the new value 142 * @return the previous value 143 */ getAndSet(T obj, long newValue)144 public long getAndSet(T obj, long newValue) { 145 long prev; 146 do { 147 prev = get(obj); 148 } while (!compareAndSet(obj, prev, newValue)); 149 return prev; 150 } 151 152 /** 153 * Atomically increments by one the current value of the field of the 154 * given object managed by this updater. 155 * 156 * @param obj An object whose field to get and set 157 * @return the previous value 158 */ getAndIncrement(T obj)159 public long getAndIncrement(T obj) { 160 long prev, next; 161 do { 162 prev = get(obj); 163 next = prev + 1; 164 } while (!compareAndSet(obj, prev, next)); 165 return prev; 166 } 167 168 /** 169 * Atomically decrements by one the current value of the field of the 170 * given object managed by this updater. 171 * 172 * @param obj An object whose field to get and set 173 * @return the previous value 174 */ getAndDecrement(T obj)175 public long getAndDecrement(T obj) { 176 long prev, next; 177 do { 178 prev = get(obj); 179 next = prev - 1; 180 } while (!compareAndSet(obj, prev, next)); 181 return prev; 182 } 183 184 /** 185 * Atomically adds the given value to the current value of the field of 186 * the given object managed by this updater. 187 * 188 * @param obj An object whose field to get and set 189 * @param delta the value to add 190 * @return the previous value 191 */ getAndAdd(T obj, long delta)192 public long getAndAdd(T obj, long delta) { 193 long prev, next; 194 do { 195 prev = get(obj); 196 next = prev + delta; 197 } while (!compareAndSet(obj, prev, next)); 198 return prev; 199 } 200 201 /** 202 * Atomically increments by one the current value of the field of the 203 * given object managed by this updater. 204 * 205 * @param obj An object whose field to get and set 206 * @return the updated value 207 */ incrementAndGet(T obj)208 public long incrementAndGet(T obj) { 209 long prev, next; 210 do { 211 prev = get(obj); 212 next = prev + 1; 213 } while (!compareAndSet(obj, prev, next)); 214 return next; 215 } 216 217 /** 218 * Atomically decrements by one the current value of the field of the 219 * given object managed by this updater. 220 * 221 * @param obj An object whose field to get and set 222 * @return the updated value 223 */ decrementAndGet(T obj)224 public long decrementAndGet(T obj) { 225 long prev, next; 226 do { 227 prev = get(obj); 228 next = prev - 1; 229 } while (!compareAndSet(obj, prev, next)); 230 return next; 231 } 232 233 /** 234 * Atomically adds the given value to the current value of the field of 235 * the given object managed by this updater. 236 * 237 * @param obj An object whose field to get and set 238 * @param delta the value to add 239 * @return the updated value 240 */ addAndGet(T obj, long delta)241 public long addAndGet(T obj, long delta) { 242 long prev, next; 243 do { 244 prev = get(obj); 245 next = prev + delta; 246 } while (!compareAndSet(obj, prev, next)); 247 return next; 248 } 249 250 /** 251 * Atomically updates the field of the given object managed by this updater 252 * with the results of applying the given function, returning the previous 253 * value. The function should be side-effect-free, since it may be 254 * re-applied when attempted updates fail due to contention among threads. 255 * 256 * @param obj An object whose field to get and set 257 * @param updateFunction a side-effect-free function 258 * @return the previous value 259 * @since 1.8 260 */ getAndUpdate(T obj, LongUnaryOperator updateFunction)261 public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) { 262 long prev, next; 263 do { 264 prev = get(obj); 265 next = updateFunction.applyAsLong(prev); 266 } while (!compareAndSet(obj, prev, next)); 267 return prev; 268 } 269 270 /** 271 * Atomically updates the field of the given object managed by this updater 272 * with the results of applying the given function, returning the updated 273 * value. The function should be side-effect-free, since it may be 274 * re-applied when attempted updates fail due to contention among threads. 275 * 276 * @param obj An object whose field to get and set 277 * @param updateFunction a side-effect-free function 278 * @return the updated value 279 * @since 1.8 280 */ updateAndGet(T obj, LongUnaryOperator updateFunction)281 public final long updateAndGet(T obj, LongUnaryOperator updateFunction) { 282 long prev, next; 283 do { 284 prev = get(obj); 285 next = updateFunction.applyAsLong(prev); 286 } while (!compareAndSet(obj, prev, next)); 287 return next; 288 } 289 290 /** 291 * Atomically updates the field of the given object managed by this 292 * updater with the results of applying the given function to the 293 * current and given values, returning the previous value. The 294 * function should be side-effect-free, since it may be re-applied 295 * when attempted updates fail due to contention among threads. The 296 * function is applied with the current value as its first argument, 297 * and the given update as the second argument. 298 * 299 * @param obj An object whose field to get and set 300 * @param x the update value 301 * @param accumulatorFunction a side-effect-free function of two arguments 302 * @return the previous value 303 * @since 1.8 304 */ getAndAccumulate(T obj, long x, LongBinaryOperator accumulatorFunction)305 public final long getAndAccumulate(T obj, long x, 306 LongBinaryOperator accumulatorFunction) { 307 long prev, next; 308 do { 309 prev = get(obj); 310 next = accumulatorFunction.applyAsLong(prev, x); 311 } while (!compareAndSet(obj, prev, next)); 312 return prev; 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 updated 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 updated value 328 * @since 1.8 329 */ accumulateAndGet(T obj, long x, LongBinaryOperator accumulatorFunction)330 public final long accumulateAndGet(T obj, long x, 331 LongBinaryOperator accumulatorFunction) { 332 long prev, next; 333 do { 334 prev = get(obj); 335 next = accumulatorFunction.applyAsLong(prev, x); 336 } while (!compareAndSet(obj, prev, next)); 337 return next; 338 } 339 340 private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> { 341 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); 342 private final long offset; 343 /** 344 * if field is protected, the subclass constructing updater, else 345 * the same as tclass 346 */ 347 private final Class<?> cclass; 348 /** class holding the field */ 349 private final Class<T> tclass; 350 CASUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller)351 CASUpdater(final Class<T> tclass, final String fieldName, 352 final Class<?> caller) { 353 final Field field; 354 final int modifiers; 355 try { 356 field = tclass.getDeclaredField(fieldName); // android-changed 357 modifiers = field.getModifiers(); 358 // BEGIN android-removed 359 // sun.reflect.misc.ReflectUtil.ensureMemberAccess( 360 // caller, tclass, null, modifiers); 361 // ClassLoader cl = tclass.getClassLoader(); 362 // ClassLoader ccl = caller.getClassLoader(); 363 // if ((ccl != null) && (ccl != cl) && 364 // ((cl == null) || !isAncestor(cl, ccl))) { 365 // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 366 // } 367 // END android-removed 368 // BEGIN android-removed 369 // } catch (PrivilegedActionException pae) { 370 // throw new RuntimeException(pae.getException()); 371 // END android-removed 372 } catch (Exception ex) { 373 throw new RuntimeException(ex); 374 } 375 376 if (field.getType() != long.class) 377 throw new IllegalArgumentException("Must be long type"); 378 379 if (!Modifier.isVolatile(modifiers)) 380 throw new IllegalArgumentException("Must be volatile type"); 381 382 this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; 383 this.tclass = tclass; 384 this.offset = U.objectFieldOffset(field); 385 } 386 387 /** 388 * Checks that target argument is instance of cclass. On 389 * failure, throws cause. 390 */ accessCheck(T obj)391 private final void accessCheck(T obj) { 392 if (!cclass.isInstance(obj)) 393 throwAccessCheckException(obj); 394 } 395 396 /** 397 * Throws access exception if accessCheck failed due to 398 * protected access, else ClassCastException. 399 */ throwAccessCheckException(T obj)400 private final void throwAccessCheckException(T obj) { 401 if (cclass == tclass) 402 throw new ClassCastException(); 403 else 404 throw new RuntimeException( 405 new IllegalAccessException( 406 "Class " + 407 cclass.getName() + 408 " can not access a protected member of class " + 409 tclass.getName() + 410 " using an instance of " + 411 obj.getClass().getName())); 412 } 413 compareAndSet(T obj, long expect, long update)414 public final boolean compareAndSet(T obj, long expect, long update) { 415 accessCheck(obj); 416 return U.compareAndSwapLong(obj, offset, expect, update); 417 } 418 weakCompareAndSet(T obj, long expect, long update)419 public final boolean weakCompareAndSet(T obj, long expect, long update) { 420 accessCheck(obj); 421 return U.compareAndSwapLong(obj, offset, expect, update); 422 } 423 set(T obj, long newValue)424 public final void set(T obj, long newValue) { 425 accessCheck(obj); 426 U.putLongVolatile(obj, offset, newValue); 427 } 428 lazySet(T obj, long newValue)429 public final void lazySet(T obj, long newValue) { 430 accessCheck(obj); 431 U.putOrderedLong(obj, offset, newValue); 432 } 433 get(T obj)434 public final long get(T obj) { 435 accessCheck(obj); 436 return U.getLongVolatile(obj, offset); 437 } 438 getAndSet(T obj, long newValue)439 public final long getAndSet(T obj, long newValue) { 440 accessCheck(obj); 441 return U.getAndSetLong(obj, offset, newValue); 442 } 443 getAndAdd(T obj, long delta)444 public final long getAndAdd(T obj, long delta) { 445 accessCheck(obj); 446 return U.getAndAddLong(obj, offset, delta); 447 } 448 getAndIncrement(T obj)449 public final long getAndIncrement(T obj) { 450 return getAndAdd(obj, 1); 451 } 452 getAndDecrement(T obj)453 public final long getAndDecrement(T obj) { 454 return getAndAdd(obj, -1); 455 } 456 incrementAndGet(T obj)457 public final long incrementAndGet(T obj) { 458 return getAndAdd(obj, 1) + 1; 459 } 460 decrementAndGet(T obj)461 public final long decrementAndGet(T obj) { 462 return getAndAdd(obj, -1) - 1; 463 } 464 addAndGet(T obj, long delta)465 public final long addAndGet(T obj, long delta) { 466 return getAndAdd(obj, delta) + delta; 467 } 468 } 469 470 private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> { 471 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); 472 private final long offset; 473 /** 474 * if field is protected, the subclass constructing updater, else 475 * the same as tclass 476 */ 477 private final Class<?> cclass; 478 /** class holding the field */ 479 private final Class<T> tclass; 480 LockedUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller)481 LockedUpdater(final Class<T> tclass, final String fieldName, 482 final Class<?> caller) { 483 Field field = null; 484 int modifiers = 0; 485 try { 486 field = tclass.getDeclaredField(fieldName); // android-changed 487 modifiers = field.getModifiers(); 488 // BEGIN android-removed 489 // sun.reflect.misc.ReflectUtil.ensureMemberAccess( 490 // caller, tclass, null, modifiers); 491 // ClassLoader cl = tclass.getClassLoader(); 492 // ClassLoader ccl = caller.getClassLoader(); 493 // if ((ccl != null) && (ccl != cl) && 494 // ((cl == null) || !isAncestor(cl, ccl))) { 495 // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 496 // } 497 // END android-removed 498 // BEGIN android-removed 499 // } catch (PrivilegedActionException pae) { 500 // throw new RuntimeException(pae.getException()); 501 // END android-removed 502 } catch (Exception ex) { 503 throw new RuntimeException(ex); 504 } 505 506 if (field.getType() != long.class) 507 throw new IllegalArgumentException("Must be long type"); 508 509 if (!Modifier.isVolatile(modifiers)) 510 throw new IllegalArgumentException("Must be volatile type"); 511 512 this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; 513 this.tclass = tclass; 514 this.offset = U.objectFieldOffset(field); 515 } 516 517 /** 518 * Checks that target argument is instance of cclass. On 519 * failure, throws cause. 520 */ accessCheck(T obj)521 private final void accessCheck(T obj) { 522 if (!cclass.isInstance(obj)) 523 throw accessCheckException(obj); 524 } 525 526 /** 527 * Returns access exception if accessCheck failed due to 528 * protected access, else ClassCastException. 529 */ accessCheckException(T obj)530 private final RuntimeException accessCheckException(T obj) { 531 if (cclass == tclass) 532 return new ClassCastException(); 533 else 534 return new RuntimeException( 535 new IllegalAccessException( 536 "Class " + 537 cclass.getName() + 538 " can not access a protected member of class " + 539 tclass.getName() + 540 " using an instance of " + 541 obj.getClass().getName())); 542 } 543 compareAndSet(T obj, long expect, long update)544 public final boolean compareAndSet(T obj, long expect, long update) { 545 accessCheck(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 weakCompareAndSet(T obj, long expect, long update)555 public final boolean weakCompareAndSet(T obj, long expect, long update) { 556 return compareAndSet(obj, expect, update); 557 } 558 set(T obj, long newValue)559 public final void set(T obj, long newValue) { 560 accessCheck(obj); 561 synchronized (this) { 562 U.putLong(obj, offset, newValue); 563 } 564 } 565 lazySet(T obj, long newValue)566 public final void lazySet(T obj, long newValue) { 567 set(obj, newValue); 568 } 569 get(T obj)570 public final long get(T obj) { 571 accessCheck(obj); 572 synchronized (this) { 573 return U.getLong(obj, offset); 574 } 575 } 576 } 577 578 // BEGIN android-removed 579 // /** 580 // * Returns true if the second classloader can be found in the first 581 // * classloader's delegation chain. 582 // * Equivalent to the inaccessible: first.isAncestor(second). 583 // */ 584 // static boolean isAncestor(ClassLoader first, ClassLoader second) { 585 // ClassLoader acl = first; 586 // do { 587 // acl = acl.getParent(); 588 // if (second == acl) { 589 // return true; 590 // } 591 // } while (acl != null); 592 // return false; 593 // } 594 // END android-removed 595 } 596