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