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