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