GNU Classpath (0.97.2) | |
Frames | No Frames |
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/licenses/publicdomain 5: */ 6: 7: package java.util.concurrent.atomic; 8: import sun.misc.Unsafe; 9: import java.lang.reflect.*; 10: 11: /** 12: * A reflection-based utility that enables atomic updates to 13: * designated <tt>volatile int</tt> fields of designated classes. 14: * This class is designed for use in atomic data structures in which 15: * several fields of the same node are independently subject to atomic 16: * updates. 17: * 18: * <p>Note that the guarantees of the {@code compareAndSet} 19: * method in this class are weaker than in other atomic classes. 20: * Because this class cannot ensure that all uses of the field 21: * are appropriate for purposes of atomic access, it can 22: * guarantee atomicity only with respect to other invocations of 23: * {@code compareAndSet} and {@code set} on the same updater. 24: * 25: * @since 1.5 26: * @author Doug Lea 27: * @param <T> The type of the object holding the updatable field 28: */ 29: public abstract class AtomicIntegerFieldUpdater<T> { 30: /** 31: * Creates and returns an updater for objects with the given field. 32: * The Class argument is needed to check that reflective types and 33: * generic types match. 34: * 35: * @param tclass the class of the objects holding the field 36: * @param fieldName the name of the field to be updated 37: * @return the updater 38: * @throws IllegalArgumentException if the field is not a 39: * volatile integer type 40: * @throws RuntimeException with a nested reflection-based 41: * exception if the class does not hold field or is the wrong type 42: */ 43: public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { 44: return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName); 45: } 46: 47: /** 48: * Protected do-nothing constructor for use by subclasses. 49: */ 50: protected AtomicIntegerFieldUpdater() { 51: } 52: 53: /** 54: * Atomically sets the field of the given object managed by this updater 55: * to the given updated value if the current value <tt>==</tt> the 56: * expected value. This method is guaranteed to be atomic with respect to 57: * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not 58: * necessarily with respect to other changes in the field. 59: * 60: * @param obj An object whose field to conditionally set 61: * @param expect the expected value 62: * @param update the new value 63: * @return true if successful 64: * @throws ClassCastException if <tt>obj</tt> is not an instance 65: * of the class possessing the field established in the constructor 66: */ 67: public abstract boolean compareAndSet(T obj, int expect, int update); 68: 69: /** 70: * Atomically sets the field of the given object managed by this updater 71: * to the given updated value if the current value <tt>==</tt> the 72: * expected value. This method is guaranteed to be atomic with respect to 73: * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not 74: * necessarily with respect to other changes in the field. 75: * May fail spuriously and does not provide ordering guarantees, 76: * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>. 77: * 78: * @param obj An object whose field to conditionally set 79: * @param expect the expected value 80: * @param update the new value 81: * @return true if successful 82: * @throws ClassCastException if <tt>obj</tt> is not an instance 83: * of the class possessing the field established in the constructor 84: */ 85: public abstract boolean weakCompareAndSet(T obj, int expect, int update); 86: 87: /** 88: * Sets the field of the given object managed by this updater to the 89: * given updated value. This operation is guaranteed to act as a volatile 90: * store with respect to subsequent invocations of 91: * <tt>compareAndSet</tt>. 92: * 93: * @param obj An object whose field to set 94: * @param newValue the new value 95: */ 96: public abstract void set(T obj, int newValue); 97: 98: /** 99: * Eventually sets the field of the given object managed by this 100: * updater to the given updated value. 101: * 102: * @param obj An object whose field to set 103: * @param newValue the new value 104: * @since 1.6 105: */ 106: public abstract void lazySet(T obj, int newValue); 107: 108: 109: /** 110: * Gets the current value held in the field of the given object managed 111: * by this updater. 112: * 113: * @param obj An object whose field to get 114: * @return the current value 115: */ 116: public abstract int get(T obj); 117: 118: /** 119: * Atomically sets the field of the given object managed by this updater 120: * to the given value and returns the old value. 121: * 122: * @param obj An object whose field to get and set 123: * @param newValue the new value 124: * @return the previous value 125: */ 126: public int getAndSet(T obj, int newValue) { 127: for (;;) { 128: int current = get(obj); 129: if (compareAndSet(obj, current, newValue)) 130: return current; 131: } 132: } 133: 134: /** 135: * Atomically increments by one the current value of the field of the 136: * given object managed by this updater. 137: * 138: * @param obj An object whose field to get and set 139: * @return the previous value 140: */ 141: public int getAndIncrement(T obj) { 142: for (;;) { 143: int current = get(obj); 144: int next = current + 1; 145: if (compareAndSet(obj, current, next)) 146: return current; 147: } 148: } 149: 150: /** 151: * Atomically decrements by one the current value of the field of the 152: * given object managed by this updater. 153: * 154: * @param obj An object whose field to get and set 155: * @return the previous value 156: */ 157: public int getAndDecrement(T obj) { 158: for (;;) { 159: int current = get(obj); 160: int next = current - 1; 161: if (compareAndSet(obj, current, next)) 162: return current; 163: } 164: } 165: 166: /** 167: * Atomically adds the given value to the current value of the field of 168: * the given object managed by this updater. 169: * 170: * @param obj An object whose field to get and set 171: * @param delta the value to add 172: * @return the previous value 173: */ 174: public int getAndAdd(T obj, int delta) { 175: for (;;) { 176: int current = get(obj); 177: int next = current + delta; 178: if (compareAndSet(obj, current, next)) 179: return current; 180: } 181: } 182: 183: /** 184: * Atomically increments by one the current value of the field of the 185: * given object managed by this updater. 186: * 187: * @param obj An object whose field to get and set 188: * @return the updated value 189: */ 190: public int incrementAndGet(T obj) { 191: for (;;) { 192: int current = get(obj); 193: int next = current + 1; 194: if (compareAndSet(obj, current, next)) 195: return next; 196: } 197: } 198: 199: /** 200: * Atomically decrements by one the current value of the field of the 201: * given object managed by this updater. 202: * 203: * @param obj An object whose field to get and set 204: * @return the updated value 205: */ 206: public int decrementAndGet(T obj) { 207: for (;;) { 208: int current = get(obj); 209: int next = current - 1; 210: if (compareAndSet(obj, current, next)) 211: return next; 212: } 213: } 214: 215: /** 216: * Atomically adds the given value to the current value of the field of 217: * the given object managed by this updater. 218: * 219: * @param obj An object whose field to get and set 220: * @param delta the value to add 221: * @return the updated value 222: */ 223: public int addAndGet(T obj, int delta) { 224: for (;;) { 225: int current = get(obj); 226: int next = current + delta; 227: if (compareAndSet(obj, current, next)) 228: return next; 229: } 230: } 231: 232: /** 233: * Standard hotspot implementation using intrinsics 234: */ 235: private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> { 236: private static final Unsafe unsafe = Unsafe.getUnsafe(); 237: private final long offset; 238: private final Class<T> tclass; 239: private final Class cclass; 240: 241: AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) { 242: Field field = null; 243: Class caller = null; 244: int modifiers = 0; 245: try { 246: field = tclass.getDeclaredField(fieldName); 247: caller = sun.reflect.Reflection.getCallerClass(3); 248: modifiers = field.getModifiers(); 249: sun.reflect.misc.ReflectUtil.ensureMemberAccess( 250: caller, tclass, null, modifiers); 251: sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 252: } catch(Exception ex) { 253: throw new RuntimeException(ex); 254: } 255: 256: Class fieldt = field.getType(); 257: if (fieldt != int.class) 258: throw new IllegalArgumentException("Must be integer type"); 259: 260: if (!Modifier.isVolatile(modifiers)) 261: throw new IllegalArgumentException("Must be volatile type"); 262: 263: this.cclass = (Modifier.isProtected(modifiers) && 264: caller != tclass) ? caller : null; 265: this.tclass = tclass; 266: offset = unsafe.objectFieldOffset(field); 267: } 268: 269: private void fullCheck(T obj) { 270: if (!tclass.isInstance(obj)) 271: throw new ClassCastException(); 272: if (cclass != null) 273: ensureProtectedAccess(obj); 274: } 275: 276: public boolean compareAndSet(T obj, int expect, int update) { 277: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 278: return unsafe.compareAndSwapInt(obj, offset, expect, update); 279: } 280: 281: public boolean weakCompareAndSet(T obj, int expect, int update) { 282: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 283: return unsafe.compareAndSwapInt(obj, offset, expect, update); 284: } 285: 286: public void set(T obj, int newValue) { 287: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 288: unsafe.putIntVolatile(obj, offset, newValue); 289: } 290: 291: public void lazySet(T obj, int newValue) { 292: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 293: unsafe.putOrderedInt(obj, offset, newValue); 294: } 295: 296: public final int get(T obj) { 297: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 298: return unsafe.getIntVolatile(obj, offset); 299: } 300: 301: private void ensureProtectedAccess(T obj) { 302: if (cclass.isInstance(obj)) { 303: return; 304: } 305: throw new RuntimeException( 306: new IllegalAccessException("Class " + 307: cclass.getName() + 308: " can not access a protected member of class " + 309: tclass.getName() + 310: " using an instance of " + 311: obj.getClass().getName() 312: ) 313: ); 314: } 315: } 316: }
GNU Classpath (0.97.2) |