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