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 sun.misc.Unsafe; 11 import java.lang.reflect.Field; 12 import java.lang.reflect.Modifier; 13 14 /** 15 * A reflection-based utility that enables atomic updates to 16 * designated {@code volatile long} fields of designated classes. 17 * This class is designed for use in atomic data structures in which 18 * several fields of the same node are independently subject to atomic 19 * updates. 20 * 21 * <p>Note that the guarantees of the {@code compareAndSet} 22 * method in this class are weaker than in other atomic classes. 23 * Because this class cannot ensure that all uses of the field 24 * are appropriate for purposes of atomic access, it can 25 * guarantee atomicity only with respect to other invocations of 26 * {@code compareAndSet} and {@code set} on the same updater. 27 * 28 * @since 1.5 29 * @author Doug Lea 30 * @param <T> The type of the object holding the updatable field 31 */ 32 public abstract class AtomicLongFieldUpdater<T> { 33 /** 34 * Creates and returns an updater for objects with the given field. 35 * The Class argument is needed to check that reflective types and 36 * generic types match. 37 * 38 * @param tclass the class of the objects holding the field 39 * @param fieldName the name of the field to be updated 40 * @return the updater 41 * @throws IllegalArgumentException if the field is not a 42 * volatile long type 43 * @throws RuntimeException with a nested reflection-based 44 * exception if the class does not hold field or is the wrong type, 45 * or the field is inaccessible to the caller according to Java language 46 * access control 47 */ 48 public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { 49 if (AtomicLong.VM_SUPPORTS_LONG_CAS) 50 return new CASUpdater<U>(tclass, fieldName); 51 else 52 return new LockedUpdater<U>(tclass, fieldName); 53 } 54 55 /** 56 * Protected do-nothing constructor for use by subclasses. 57 */ 58 protected AtomicLongFieldUpdater() { 59 } 60 61 /** 62 * Atomically sets the field of the given object managed by this updater 63 * to the given updated value if the current value {@code ==} the 64 * expected value. This method is guaranteed to be atomic with respect to 65 * other calls to {@code compareAndSet} and {@code set}, but not 66 * necessarily with respect to other changes in the field. 67 * 68 * @param obj An object whose field to conditionally set 69 * @param expect the expected value 70 * @param update the new value 71 * @return true if successful 72 * @throws ClassCastException if {@code obj} is not an instance 73 * of the class possessing the field established in the constructor 74 */ 75 public abstract boolean compareAndSet(T obj, long expect, long update); 76 77 /** 78 * Atomically sets the field of the given object managed by this updater 79 * to the given updated value if the current value {@code ==} the 80 * expected value. This method is guaranteed to be atomic with respect to 81 * other calls to {@code compareAndSet} and {@code set}, but not 82 * necessarily with respect to other changes in the field. 83 * 84 * <p><a href="package-summary.html#weakCompareAndSet">May fail 85 * spuriously and does not provide ordering guarantees</a>, so is 86 * only rarely an appropriate alternative to {@code compareAndSet}. 87 * 88 * @param obj An object whose field to conditionally set 89 * @param expect the expected value 90 * @param update the new value 91 * @return true if successful 92 * @throws ClassCastException if {@code obj} is not an instance 93 * of the class possessing the field established in the constructor 94 */ 95 public abstract boolean weakCompareAndSet(T obj, long expect, long update); 96 97 /** 98 * Sets the field of the given object managed by this updater to the 99 * given updated value. This operation is guaranteed to act as a volatile 100 * store with respect to subsequent invocations of {@code compareAndSet}. 101 * 102 * @param obj An object whose field to set 103 * @param newValue the new value 104 */ 105 public abstract void set(T obj, long newValue); 106 107 /** 108 * Eventually sets the field of the given object managed by this 109 * updater to the given updated value. 110 * 111 * @param obj An object whose field to set 112 * @param newValue the new value 113 * @since 1.6 114 */ 115 public abstract void lazySet(T obj, long newValue); 116 117 /** 118 * Gets the current value held in the field of the given object managed 119 * by this updater. 120 * 121 * @param obj An object whose field to get 122 * @return the current value 123 */ 124 public abstract long get(T obj); 125 126 /** 127 * Atomically sets the field of the given object managed by this updater 128 * to the given value and returns the old value. 129 * 130 * @param obj An object whose field to get and set 131 * @param newValue the new value 132 * @return the previous value 133 */ 134 public long getAndSet(T obj, long newValue) { 135 for (;;) { 136 long current = get(obj); 137 if (compareAndSet(obj, current, newValue)) 138 return current; 139 } 140 } 141 142 /** 143 * Atomically increments by one the current value of the field of the 144 * given object managed by this updater. 145 * 146 * @param obj An object whose field to get and set 147 * @return the previous value 148 */ 149 public long getAndIncrement(T obj) { 150 for (;;) { 151 long current = get(obj); 152 long next = current + 1; 153 if (compareAndSet(obj, current, next)) 154 return current; 155 } 156 } 157 158 /** 159 * Atomically decrements by one the current value of the field of the 160 * given object managed by this updater. 161 * 162 * @param obj An object whose field to get and set 163 * @return the previous value 164 */ 165 public long getAndDecrement(T obj) { 166 for (;;) { 167 long current = get(obj); 168 long next = current - 1; 169 if (compareAndSet(obj, current, next)) 170 return current; 171 } 172 } 173 174 /** 175 * Atomically adds the given value to the current value of the field of 176 * the given object managed by this updater. 177 * 178 * @param obj An object whose field to get and set 179 * @param delta the value to add 180 * @return the previous value 181 */ 182 public long getAndAdd(T obj, long delta) { 183 for (;;) { 184 long current = get(obj); 185 long next = current + delta; 186 if (compareAndSet(obj, current, next)) 187 return current; 188 } 189 } 190 191 /** 192 * Atomically increments by one the current value of the field of the 193 * given object managed by this updater. 194 * 195 * @param obj An object whose field to get and set 196 * @return the updated value 197 */ 198 public long incrementAndGet(T obj) { 199 for (;;) { 200 long current = get(obj); 201 long next = current + 1; 202 if (compareAndSet(obj, current, next)) 203 return next; 204 } 205 } 206 207 /** 208 * Atomically decrements by one the current value of the field of the 209 * given object managed by this updater. 210 * 211 * @param obj An object whose field to get and set 212 * @return the updated value 213 */ 214 public long decrementAndGet(T obj) { 215 for (;;) { 216 long current = get(obj); 217 long next = current - 1; 218 if (compareAndSet(obj, current, next)) 219 return next; 220 } 221 } 222 223 /** 224 * Atomically adds the given value to the current value of the field of 225 * the given object managed by this updater. 226 * 227 * @param obj An object whose field to get and set 228 * @param delta the value to add 229 * @return the updated value 230 */ 231 public long addAndGet(T obj, long delta) { 232 for (;;) { 233 long current = get(obj); 234 long next = current + delta; 235 if (compareAndSet(obj, current, next)) 236 return next; 237 } 238 } 239 240 private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> { 241 private static final Unsafe unsafe = Unsafe.getUnsafe(); 242 private final long offset; 243 private final Class<T> tclass; 244 private final Class<?> cclass; 245 246 CASUpdater(Class<T> tclass, String fieldName) { 247 final Field field; 248 final Class<?> caller; 249 final int modifiers; 250 try { 251 field = tclass.getDeclaredField(fieldName); // android-changed 252 caller = VMStack.getStackClass2(); // android-changed 253 modifiers = field.getModifiers(); 254 // BEGIN android-removed 255 // sun.reflect.misc.ReflectUtil.ensureMemberAccess( 256 // caller, tclass, null, modifiers); 257 // ClassLoader cl = tclass.getClassLoader(); 258 // ClassLoader ccl = caller.getClassLoader(); 259 // if ((ccl != null) && (ccl != cl) && 260 // ((cl == null) || !isAncestor(cl, ccl))) { 261 // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 262 // } 263 // END android-removed 264 // BEGIN android-removed 265 // } catch (PrivilegedActionException pae) { 266 // throw new RuntimeException(pae.getException()); 267 // END android-removed 268 } catch (Exception ex) { 269 throw new RuntimeException(ex); 270 } 271 272 Class<?> fieldt = field.getType(); 273 if (fieldt != long.class) 274 throw new IllegalArgumentException("Must be long type"); 275 276 if (!Modifier.isVolatile(modifiers)) 277 throw new IllegalArgumentException("Must be volatile type"); 278 279 this.cclass = (Modifier.isProtected(modifiers) && 280 caller != tclass) ? caller : null; 281 this.tclass = tclass; 282 offset = unsafe.objectFieldOffset(field); 283 } 284 285 private void fullCheck(T obj) { 286 if (!tclass.isInstance(obj)) 287 throw new ClassCastException(); 288 if (cclass != null) 289 ensureProtectedAccess(obj); 290 } 291 292 public boolean compareAndSet(T obj, long expect, long update) { 293 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 294 return unsafe.compareAndSwapLong(obj, offset, expect, update); 295 } 296 297 public boolean weakCompareAndSet(T obj, long expect, long update) { 298 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 299 return unsafe.compareAndSwapLong(obj, offset, expect, update); 300 } 301 302 public void set(T obj, long newValue) { 303 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 304 unsafe.putLongVolatile(obj, offset, newValue); 305 } 306 307 public void lazySet(T obj, long newValue) { 308 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 309 unsafe.putOrderedLong(obj, offset, newValue); 310 } 311 312 public long get(T obj) { 313 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 314 return unsafe.getLongVolatile(obj, offset); 315 } 316 317 private void ensureProtectedAccess(T obj) { 318 if (cclass.isInstance(obj)) { 319 return; 320 } 321 throw new RuntimeException( 322 new IllegalAccessException("Class " + 323 cclass.getName() + 324 " can not access a protected member of class " + 325 tclass.getName() + 326 " using an instance of " + 327 obj.getClass().getName() 328 ) 329 ); 330 } 331 } 332 333 334 private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> { 335 private static final Unsafe unsafe = Unsafe.getUnsafe(); 336 private final long offset; 337 private final Class<T> tclass; 338 private final Class<?> cclass; 339 340 LockedUpdater(Class<T> tclass, String fieldName) { 341 Field field = null; 342 Class<?> caller = null; 343 int modifiers = 0; 344 try { 345 field = tclass.getDeclaredField(fieldName); // android-changed 346 caller = VMStack.getStackClass2(); // android-changed 347 modifiers = field.getModifiers(); 348 // BEGIN android-removed 349 // sun.reflect.misc.ReflectUtil.ensureMemberAccess( 350 // caller, tclass, null, modifiers); 351 // ClassLoader cl = tclass.getClassLoader(); 352 // ClassLoader ccl = caller.getClassLoader(); 353 // if ((ccl != null) && (ccl != cl) && 354 // ((cl == null) || !isAncestor(cl, ccl))) { 355 // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 356 // } 357 // END android-removed 358 // BEGIN android-removed 359 // } catch (PrivilegedActionException pae) { 360 // throw new RuntimeException(pae.getException()); 361 // END android-removed 362 } catch (Exception ex) { 363 throw new RuntimeException(ex); 364 } 365 366 Class<?> fieldt = field.getType(); 367 if (fieldt != long.class) 368 throw new IllegalArgumentException("Must be long type"); 369 370 if (!Modifier.isVolatile(modifiers)) 371 throw new IllegalArgumentException("Must be volatile type"); 372 373 this.cclass = (Modifier.isProtected(modifiers) && 374 caller != tclass) ? caller : null; 375 this.tclass = tclass; 376 offset = unsafe.objectFieldOffset(field); 377 } 378 379 private void fullCheck(T obj) { 380 if (!tclass.isInstance(obj)) 381 throw new ClassCastException(); 382 if (cclass != null) 383 ensureProtectedAccess(obj); 384 } 385 386 public boolean compareAndSet(T obj, long expect, long update) { 387 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 388 synchronized (this) { 389 long v = unsafe.getLong(obj, offset); 390 if (v != expect) 391 return false; 392 unsafe.putLong(obj, offset, update); 393 return true; 394 } 395 } 396 397 public boolean weakCompareAndSet(T obj, long expect, long update) { 398 return compareAndSet(obj, expect, update); 399 } 400 401 public void set(T obj, long newValue) { 402 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 403 synchronized (this) { 404 unsafe.putLong(obj, offset, newValue); 405 } 406 } 407 408 public void lazySet(T obj, long newValue) { 409 set(obj, newValue); 410 } 411 412 public long get(T obj) { 413 if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 414 synchronized (this) { 415 return unsafe.getLong(obj, offset); 416 } 417 } 418 419 private void ensureProtectedAccess(T obj) { 420 if (cclass.isInstance(obj)) { 421 return; 422 } 423 throw new RuntimeException( 424 new IllegalAccessException("Class " + 425 cclass.getName() + 426 " can not access a protected member of class " + 427 tclass.getName() + 428 " using an instance of " + 429 obj.getClass().getName() 430 ) 431 ); 432 } 433 } 434 435 // BEGIN android-removed 436 // /** 437 // * Returns true if the second classloader can be found in the first 438 // * classloader's delegation chain. 439 // * Equivalent to the inaccessible: first.isAncestor(second). 440 // */ 441 // private static boolean isAncestor(ClassLoader first, ClassLoader second) { 442 // ClassLoader acl = first; 443 // do { 444 // acl = acl.getParent(); 445 // if (second == acl) { 446 // return true; 447 // } 448 // } while (acl != null); 449 // return false; 450 // } 451 // END android-removed 452 } 453