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