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