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.BinaryOperator; 16 import java.util.function.UnaryOperator; 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} reference fields of designated 23 * classes. This class is designed for use in atomic data structures 24 * in which several reference fields of the same node are 25 * independently subject to atomic updates. For example, a tree node 26 * might be declared as 27 * 28 * <pre> {@code 29 * class Node { 30 * private volatile Node left, right; 31 * 32 * private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater = 33 * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left"); 34 * private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater = 35 * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right"); 36 * 37 * Node getLeft() { return left; } 38 * boolean compareAndSetLeft(Node expect, Node update) { 39 * return leftUpdater.compareAndSet(this, expect, update); 40 * } 41 * // ... and so on 42 * }}</pre> 43 * 44 * <p>Note that the guarantees of the {@code compareAndSet} 45 * method in this class are weaker than in other atomic classes. 46 * Because this class cannot ensure that all uses of the field 47 * are appropriate for purposes of atomic access, it can 48 * guarantee atomicity only with respect to other invocations of 49 * {@code compareAndSet} and {@code set} on the same updater. 50 * 51 * @since 1.5 52 * @author Doug Lea 53 * @param <T> The type of the object holding the updatable field 54 * @param <V> The type of the field 55 */ 56 public abstract class AtomicReferenceFieldUpdater<T,V> { 57 58 /** 59 * Creates and returns an updater for objects with the given field. 60 * The Class arguments are needed to check that reflective types and 61 * generic types match. 62 * 63 * @param tclass the class of the objects holding the field 64 * @param vclass the class of the field 65 * @param fieldName the name of the field to be updated 66 * @param <U> the type of instances of tclass 67 * @param <W> the type of instances of vclass 68 * @return the updater 69 * @throws ClassCastException if the field is of the wrong type 70 * @throws IllegalArgumentException if the field is not volatile 71 * @throws RuntimeException with a nested reflection-based 72 * exception if the class does not hold field or is the wrong type, 73 * or the field is inaccessible to the caller according to Java language 74 * access control 75 */ 76 @CallerSensitive newUpdater(Class<U> tclass, Class<W> vclass, String fieldName)77 public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, 78 Class<W> vclass, 79 String fieldName) { 80 return new AtomicReferenceFieldUpdaterImpl<U,W> 81 (tclass, vclass, fieldName, VMStack.getStackClass1()); // android-changed 82 } 83 84 /** 85 * Protected do-nothing constructor for use by subclasses. 86 */ AtomicReferenceFieldUpdater()87 protected AtomicReferenceFieldUpdater() { 88 } 89 90 /** 91 * Atomically sets the field of the given object managed by this updater 92 * to the given updated value if the current value {@code ==} the 93 * expected value. This method is guaranteed to be atomic with respect to 94 * other calls to {@code compareAndSet} and {@code set}, but not 95 * necessarily with respect to other changes in the field. 96 * 97 * @param obj An object whose field to conditionally set 98 * @param expect the expected value 99 * @param update the new value 100 * @return {@code true} if successful 101 */ compareAndSet(T obj, V expect, V update)102 public abstract boolean compareAndSet(T obj, V expect, V update); 103 104 /** 105 * Atomically sets the field of the given object managed by this updater 106 * to the given updated value if the current value {@code ==} the 107 * expected value. This method is guaranteed to be atomic with respect to 108 * other calls to {@code compareAndSet} and {@code set}, but not 109 * necessarily with respect to other changes in the field. 110 * 111 * <p><a href="package-summary.html#weakCompareAndSet">May fail 112 * spuriously and does not provide ordering guarantees</a>, so is 113 * only rarely an appropriate alternative to {@code compareAndSet}. 114 * 115 * @param obj An object whose field to conditionally set 116 * @param expect the expected value 117 * @param update the new value 118 * @return {@code true} if successful 119 */ weakCompareAndSet(T obj, V expect, V update)120 public abstract boolean weakCompareAndSet(T obj, V expect, V update); 121 122 /** 123 * Sets the field of the given object managed by this updater to the 124 * given updated value. This operation is guaranteed to act as a volatile 125 * store with respect to subsequent invocations of {@code compareAndSet}. 126 * 127 * @param obj An object whose field to set 128 * @param newValue the new value 129 */ set(T obj, V newValue)130 public abstract void set(T obj, V newValue); 131 132 /** 133 * Eventually sets the field of the given object managed by this 134 * updater to the given updated value. 135 * 136 * @param obj An object whose field to set 137 * @param newValue the new value 138 * @since 1.6 139 */ lazySet(T obj, V newValue)140 public abstract void lazySet(T obj, V newValue); 141 142 /** 143 * Gets the current value held in the field of the given object managed 144 * by this updater. 145 * 146 * @param obj An object whose field to get 147 * @return the current value 148 */ get(T obj)149 public abstract V get(T obj); 150 151 /** 152 * Atomically sets the field of the given object managed by this updater 153 * to the given value and returns the old value. 154 * 155 * @param obj An object whose field to get and set 156 * @param newValue the new value 157 * @return the previous value 158 */ getAndSet(T obj, V newValue)159 public V getAndSet(T obj, V newValue) { 160 V prev; 161 do { 162 prev = get(obj); 163 } while (!compareAndSet(obj, prev, newValue)); 164 return prev; 165 } 166 167 /** 168 * Atomically updates the field of the given object managed by this updater 169 * with the results of applying the given function, returning the previous 170 * value. The function should be side-effect-free, since it may be 171 * re-applied when attempted updates fail due to contention among threads. 172 * 173 * @param obj An object whose field to get and set 174 * @param updateFunction a side-effect-free function 175 * @return the previous value 176 * @since 1.8 177 */ getAndUpdate(T obj, UnaryOperator<V> updateFunction)178 public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) { 179 V prev, next; 180 do { 181 prev = get(obj); 182 next = updateFunction.apply(prev); 183 } while (!compareAndSet(obj, prev, next)); 184 return prev; 185 } 186 187 /** 188 * Atomically updates the field of the given object managed by this updater 189 * with the results of applying the given function, returning the updated 190 * value. The function should be side-effect-free, since it may be 191 * re-applied when attempted updates fail due to contention among threads. 192 * 193 * @param obj An object whose field to get and set 194 * @param updateFunction a side-effect-free function 195 * @return the updated value 196 * @since 1.8 197 */ updateAndGet(T obj, UnaryOperator<V> updateFunction)198 public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) { 199 V prev, next; 200 do { 201 prev = get(obj); 202 next = updateFunction.apply(prev); 203 } while (!compareAndSet(obj, prev, next)); 204 return next; 205 } 206 207 /** 208 * Atomically updates the field of the given object managed by this 209 * updater with the results of applying the given function to the 210 * current and given values, returning the previous value. The 211 * function should be side-effect-free, since it may be re-applied 212 * when attempted updates fail due to contention among threads. The 213 * function is applied with the current value as its first argument, 214 * and the given update as the second argument. 215 * 216 * @param obj An object whose field to get and set 217 * @param x the update value 218 * @param accumulatorFunction a side-effect-free function of two arguments 219 * @return the previous value 220 * @since 1.8 221 */ getAndAccumulate(T obj, V x, BinaryOperator<V> accumulatorFunction)222 public final V getAndAccumulate(T obj, V x, 223 BinaryOperator<V> accumulatorFunction) { 224 V prev, next; 225 do { 226 prev = get(obj); 227 next = accumulatorFunction.apply(prev, x); 228 } while (!compareAndSet(obj, prev, next)); 229 return prev; 230 } 231 232 /** 233 * Atomically updates the field of the given object managed by this 234 * updater with the results of applying the given function to the 235 * current and given values, returning the updated value. The 236 * function should be side-effect-free, since it may be re-applied 237 * when attempted updates fail due to contention among threads. The 238 * function is applied with the current value as its first argument, 239 * and the given update as the second argument. 240 * 241 * @param obj An object whose field to get and set 242 * @param x the update value 243 * @param accumulatorFunction a side-effect-free function of two arguments 244 * @return the updated value 245 * @since 1.8 246 */ accumulateAndGet(T obj, V x, BinaryOperator<V> accumulatorFunction)247 public final V accumulateAndGet(T obj, V x, 248 BinaryOperator<V> accumulatorFunction) { 249 V prev, next; 250 do { 251 prev = get(obj); 252 next = accumulatorFunction.apply(prev, x); 253 } while (!compareAndSet(obj, prev, next)); 254 return next; 255 } 256 257 private static final class AtomicReferenceFieldUpdaterImpl<T,V> 258 extends AtomicReferenceFieldUpdater<T,V> { 259 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); 260 private final long offset; 261 /** 262 * if field is protected, the subclass constructing updater, else 263 * the same as tclass 264 */ 265 private final Class<?> cclass; 266 /** class holding the field */ 267 private final Class<T> tclass; 268 /** field value type */ 269 private final Class<V> vclass; 270 271 /* 272 * Internal type checks within all update methods contain 273 * internal inlined optimizations checking for the common 274 * cases where the class is final (in which case a simple 275 * getClass comparison suffices) or is of type Object (in 276 * which case no check is needed because all objects are 277 * instances of Object). The Object case is handled simply by 278 * setting vclass to null in constructor. The targetCheck and 279 * updateCheck methods are invoked when these faster 280 * screenings fail. 281 */ 282 AtomicReferenceFieldUpdaterImpl(final Class<T> tclass, final Class<V> vclass, final String fieldName, final Class<?> caller)283 AtomicReferenceFieldUpdaterImpl(final Class<T> tclass, 284 final Class<V> vclass, 285 final String fieldName, 286 final Class<?> caller) { 287 final Field field; 288 final Class<?> fieldClass; 289 final int modifiers; 290 try { 291 field = tclass.getDeclaredField(fieldName); // android-changed 292 modifiers = field.getModifiers(); 293 // BEGIN android-removed 294 // sun.reflect.misc.ReflectUtil.ensureMemberAccess( 295 // caller, tclass, null, modifiers); 296 // ClassLoader cl = tclass.getClassLoader(); 297 // ClassLoader ccl = caller.getClassLoader(); 298 // if ((ccl != null) && (ccl != cl) && 299 // ((cl == null) || !isAncestor(cl, ccl))) { 300 // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 301 // } 302 // END android-removed 303 fieldClass = field.getType(); 304 // BEGIN android-removed 305 // } catch (PrivilegedActionException pae) { 306 // throw new RuntimeException(pae.getException()); 307 // END android-removed 308 } catch (Exception ex) { 309 throw new RuntimeException(ex); 310 } 311 312 if (vclass != fieldClass) 313 throw new ClassCastException(); 314 if (vclass.isPrimitive()) 315 throw new IllegalArgumentException("Must be reference type"); 316 317 if (!Modifier.isVolatile(modifiers)) 318 throw new IllegalArgumentException("Must be volatile type"); 319 320 this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; 321 this.tclass = tclass; 322 this.vclass = vclass; 323 this.offset = U.objectFieldOffset(field); 324 } 325 326 // BEGIN android-removed 327 // /** 328 // * Returns true if the second classloader can be found in the first 329 // * classloader's delegation chain. 330 // * Equivalent to the inaccessible: first.isAncestor(second). 331 // */ 332 // private static boolean isAncestor(ClassLoader first, ClassLoader second) { 333 // ClassLoader acl = first; 334 // do { 335 // acl = acl.getParent(); 336 // if (second == acl) { 337 // return true; 338 // } 339 // } while (acl != null); 340 // return false; 341 // } 342 // END android-removed 343 344 /** 345 * Checks that target argument is instance of cclass. On 346 * failure, throws cause. 347 */ accessCheck(T obj)348 private final void accessCheck(T obj) { 349 if (!cclass.isInstance(obj)) 350 throwAccessCheckException(obj); 351 } 352 353 /** 354 * Throws access exception if accessCheck failed due to 355 * protected access, else ClassCastException. 356 */ throwAccessCheckException(T obj)357 private final void throwAccessCheckException(T obj) { 358 if (cclass == tclass) 359 throw new ClassCastException(); 360 else 361 throw new RuntimeException( 362 new IllegalAccessException( 363 "Class " + 364 cclass.getName() + 365 " can not access a protected member of class " + 366 tclass.getName() + 367 " using an instance of " + 368 obj.getClass().getName())); 369 } 370 valueCheck(V v)371 private final void valueCheck(V v) { 372 if (v != null && !(vclass.isInstance(v))) 373 throwCCE(); 374 } 375 throwCCE()376 static void throwCCE() { 377 throw new ClassCastException(); 378 } 379 compareAndSet(T obj, V expect, V update)380 public final boolean compareAndSet(T obj, V expect, V update) { 381 accessCheck(obj); 382 valueCheck(update); 383 return U.compareAndSwapObject(obj, offset, expect, update); 384 } 385 weakCompareAndSet(T obj, V expect, V update)386 public final boolean weakCompareAndSet(T obj, V expect, V update) { 387 // same implementation as strong form for now 388 accessCheck(obj); 389 valueCheck(update); 390 return U.compareAndSwapObject(obj, offset, expect, update); 391 } 392 set(T obj, V newValue)393 public final void set(T obj, V newValue) { 394 accessCheck(obj); 395 valueCheck(newValue); 396 U.putObjectVolatile(obj, offset, newValue); 397 } 398 lazySet(T obj, V newValue)399 public final void lazySet(T obj, V newValue) { 400 accessCheck(obj); 401 valueCheck(newValue); 402 U.putOrderedObject(obj, offset, newValue); 403 } 404 405 @SuppressWarnings("unchecked") get(T obj)406 public final V get(T obj) { 407 accessCheck(obj); 408 return (V)U.getObjectVolatile(obj, offset); 409 } 410 411 @SuppressWarnings("unchecked") getAndSet(T obj, V newValue)412 public final V getAndSet(T obj, V newValue) { 413 accessCheck(obj); 414 valueCheck(newValue); 415 return (V)U.getAndSetObject(obj, offset, newValue); 416 } 417 } 418 } 419