AtomicLongFieldUpdater.java revision a807b4d808d2591894daf13aab179b2e9c46a2f5
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Written by Doug Lea with assistance from members of JCP JSR-166 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Expert Group and released to the public domain, as explained at 4a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * http://creativecommons.org/publicdomain/zero/1.0/ 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util.concurrent.atomic; 87365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson 98eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilsonimport dalvik.system.VMStack; // android-added 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport sun.misc.Unsafe; 118eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilsonimport java.lang.reflect.*; 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A reflection-based utility that enables atomic updates to 15bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * designated {@code volatile long} fields of designated classes. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class is designed for use in atomic data structures in which 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * several fields of the same node are independently subject to atomic 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * updates. 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 20bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * <p>Note that the guarantees of the {@code compareAndSet} 21bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * method in this class are weaker than in other atomic classes. 22bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Because this class cannot ensure that all uses of the field 23bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * are appropriate for purposes of atomic access, it can 24bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * guarantee atomicity only with respect to other invocations of 25bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * {@code compareAndSet} and {@code set} on the same updater. 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @since 1.5 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Doug Lea 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param <T> The type of the object holding the updatable field 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 318eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilsonpublic abstract class AtomicLongFieldUpdater<T> { 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 33bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Creates and returns an updater for objects with the given field. 34bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * The Class argument is needed to check that reflective types and 35bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * generic types match. 36bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param tclass the class of the objects holding the field 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param fieldName the name of the field to be updated. 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the updater 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException if the field is not a 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * volatile long type. 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws RuntimeException with a nested reflection-based 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exception if the class does not hold field or is the wrong type. 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (AtomicLong.VM_SUPPORTS_LONG_CAS) 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new CASUpdater<U>(tclass, fieldName); 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project else 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new LockedUpdater<U>(tclass, fieldName); 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Protected do-nothing constructor for use by subclasses. 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected AtomicLongFieldUpdater() { 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 59bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically sets the field of the given object managed by this updater 60bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * to the given updated value if the current value {@code ==} the 61bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * expected value. This method is guaranteed to be atomic with respect to 62bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * other calls to {@code compareAndSet} and {@code set}, but not 63bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * necessarily with respect to other changes in the field. 64bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to conditionally set 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param expect the expected value 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param update the new value 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if successful. 69bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @throws ClassCastException if {@code obj} is not an instance 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the class possessing the field established in the constructor. 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public abstract boolean compareAndSet(T obj, long expect, long update); 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 75bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically sets the field of the given object managed by this updater 76bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * to the given updated value if the current value {@code ==} the 77bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * expected value. This method is guaranteed to be atomic with respect to 78bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * other calls to {@code compareAndSet} and {@code set}, but not 79bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * necessarily with respect to other changes in the field. 80bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 81bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> 82bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * and does not provide ordering guarantees, so is only rarely an 83bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * appropriate alternative to {@code compareAndSet}. 84bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to conditionally set 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param expect the expected value 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param update the new value 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if successful. 89bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @throws ClassCastException if {@code obj} is not an instance 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the class possessing the field established in the constructor. 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public abstract boolean weakCompareAndSet(T obj, long expect, long update); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 95bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Sets the field of the given object managed by this updater to the 96bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * given updated value. This operation is guaranteed to act as a volatile 97bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * store with respect to subsequent invocations of {@code compareAndSet}. 98bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to set 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newValue the new value 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public abstract void set(T obj, long newValue); 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1056232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson * Eventually sets the field of the given object managed by this 1066232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson * updater to the given updated value. 1076232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson * 1086232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson * @param obj An object whose field to set 1096232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson * @param newValue the new value 1106232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson * @since 1.6 1116232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson */ 1126232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson public abstract void lazySet(T obj, long newValue); 1136232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson 1146232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson /** 115bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Gets the current value held in the field of the given object managed 116bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * by this updater. 117bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the current value 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public abstract long get(T obj); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 124bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically sets the field of the given object managed by this updater 125bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * to the given value and returns the old value. 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get and set 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newValue the new value 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the previous value 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long getAndSet(T obj, long newValue) { 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (;;) { 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long current = get(obj); 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (compareAndSet(obj, current, newValue)) 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return current; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 140bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically increments by one the current value of the field of the 141bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * given object managed by this updater. 142bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get and set 144bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @return the previous value 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long getAndIncrement(T obj) { 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (;;) { 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long current = get(obj); 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long next = current + 1; 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (compareAndSet(obj, current, next)) 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return current; 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 156bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically decrements by one the current value of the field of the 157bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * given object managed by this updater. 158bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get and set 160bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @return the previous value 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long getAndDecrement(T obj) { 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (;;) { 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long current = get(obj); 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long next = current - 1; 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (compareAndSet(obj, current, next)) 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return current; 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 172bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically adds the given value to the current value of the field of 173bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * the given object managed by this updater. 174bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get and set 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param delta the value to add 177bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @return the previous value 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long getAndAdd(T obj, long delta) { 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (;;) { 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long current = get(obj); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long next = current + delta; 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (compareAndSet(obj, current, next)) 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return current; 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 189bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically increments by one the current value of the field of the 190bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * given object managed by this updater. 191bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get and set 193bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @return the updated value 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long incrementAndGet(T obj) { 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (;;) { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long current = get(obj); 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long next = current + 1; 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (compareAndSet(obj, current, next)) 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return next; 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 205bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically decrements by one the current value of the field of the 206bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * given object managed by this updater. 207bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get and set 209bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @return the updated value 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long decrementAndGet(T obj) { 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (;;) { 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long current = get(obj); 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long next = current - 1; 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (compareAndSet(obj, current, next)) 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return next; 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 221bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Atomically adds the given value to the current value of the field of 222bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * the given object managed by this updater. 223bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj An object whose field to get and set 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param delta the value to add 226bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * @return the updated value 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long addAndGet(T obj, long delta) { 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (;;) { 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long current = get(obj); 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long next = current + delta; 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (compareAndSet(obj, current, next)) 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return next; 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> { 238a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson private static final Unsafe unsafe = Unsafe.getUnsafe(); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final long offset; 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Class<T> tclass; 241a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson private final Class<?> cclass; 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CASUpdater(Class<T> tclass, String fieldName) { 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Field field = null; 245a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson Class<?> caller = null; 246bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson int modifiers = 0; 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field = tclass.getDeclaredField(fieldName); 2496232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson caller = VMStack.getStackClass2(); // android-changed 250bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson modifiers = field.getModifiers(); 2516232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // BEGIN android-removed 2526232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // sun.reflect.misc.ReflectUtil.ensureMemberAccess( 2536232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // caller, tclass, null, modifiers); 2546232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 2556232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // END android-removed 256bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } catch (Exception ex) { 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new RuntimeException(ex); 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 259bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 260a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson Class<?> fieldt = field.getType(); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fieldt != long.class) 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Must be long type"); 263bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 264bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (!Modifier.isVolatile(modifiers)) 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Must be volatile type"); 266bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 267bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson this.cclass = (Modifier.isProtected(modifiers) && 268bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson caller != tclass) ? caller : null; 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.tclass = tclass; 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project offset = unsafe.objectFieldOffset(field); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 273bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson private void fullCheck(T obj) { 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!tclass.isInstance(obj)) 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ClassCastException(); 276bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (cclass != null) 277bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson ensureProtectedAccess(obj); 278bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } 279bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 280bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson public boolean compareAndSet(T obj, long expect, long update) { 281bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return unsafe.compareAndSwapLong(obj, offset, expect, update); 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean weakCompareAndSet(T obj, long expect, long update) { 286bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return unsafe.compareAndSwapLong(obj, offset, expect, update); 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void set(T obj, long newValue) { 291bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unsafe.putLongVolatile(obj, offset, newValue); 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2956232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson public void lazySet(T obj, long newValue) { 2966232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 2976232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson unsafe.putOrderedLong(obj, offset, newValue); 2986232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson } 2996232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long get(T obj) { 301bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return unsafe.getLongVolatile(obj, offset); 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 304bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 305bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson private void ensureProtectedAccess(T obj) { 306bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (cclass.isInstance(obj)) { 307bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson return; 308bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } 3098eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson throw new RuntimeException( 310bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson new IllegalAccessException("Class " + 311bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson cclass.getName() + 312bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson " can not access a protected member of class " + 313bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson tclass.getName() + 314bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson " using an instance of " + 315bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson obj.getClass().getName() 316bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson ) 317bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson ); 318bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> { 323a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson private static final Unsafe unsafe = Unsafe.getUnsafe(); 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final long offset; 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Class<T> tclass; 326a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson private final Class<?> cclass; 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LockedUpdater(Class<T> tclass, String fieldName) { 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Field field = null; 330a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson Class<?> caller = null; 331bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson int modifiers = 0; 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project field = tclass.getDeclaredField(fieldName); 3346232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson caller = VMStack.getStackClass2(); // android-changed 335bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson modifiers = field.getModifiers(); 3366232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // BEGIN android-removed 3376232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // sun.reflect.misc.ReflectUtil.ensureMemberAccess( 3386232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // caller, tclass, null, modifiers); 3396232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 3406232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson // END android-removed 341bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } catch (Exception ex) { 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new RuntimeException(ex); 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 344bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 345a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson Class<?> fieldt = field.getType(); 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fieldt != long.class) 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Must be long type"); 348bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 349bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (!Modifier.isVolatile(modifiers)) 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Must be volatile type"); 351bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 352bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson this.cclass = (Modifier.isProtected(modifiers) && 353bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson caller != tclass) ? caller : null; 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.tclass = tclass; 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project offset = unsafe.objectFieldOffset(field); 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 358bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson private void fullCheck(T obj) { 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!tclass.isInstance(obj)) 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ClassCastException(); 361bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (cclass != null) 362bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson ensureProtectedAccess(obj); 363bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } 364bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 365bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson public boolean compareAndSet(T obj, long expect, long update) { 366bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 3678eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson synchronized (this) { 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project long v = unsafe.getLong(obj, offset); 369bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (v != expect) 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unsafe.putLong(obj, offset, update); 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean weakCompareAndSet(T obj, long expect, long update) { 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return compareAndSet(obj, expect, update); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void set(T obj, long newValue) { 381bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 3828eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson synchronized (this) { 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unsafe.putLong(obj, offset, newValue); 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 387bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson public void lazySet(T obj, long newValue) { 388bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson set(obj, newValue); 389bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } 390bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public long get(T obj) { 392bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); 3938eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson synchronized (this) { 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return unsafe.getLong(obj, offset); 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 397bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson 398bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson private void ensureProtectedAccess(T obj) { 399bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson if (cclass.isInstance(obj)) { 400bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson return; 401bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } 4028eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson throw new RuntimeException( 403bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson new IllegalAccessException("Class " + 404bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson cclass.getName() + 405bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson " can not access a protected member of class " + 406bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson tclass.getName() + 407bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson " using an instance of " + 408bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson obj.getClass().getName() 409bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson ) 410bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson ); 411bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson } 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 414