• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
newUpdater(Class<U> tclass, String fieldName)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      */
AtomicIntegerFieldUpdater()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      */
compareAndSet(T obj, int expect, int update)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      */
weakCompareAndSet(T obj, int expect, int update)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      */
set(T obj, int newValue)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      */
lazySet(T obj, int newValue)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      */
get(T obj)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      */
getAndSet(T obj, int newValue)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      */
getAndIncrement(T obj)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      */
getAndDecrement(T obj)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      */
getAndAdd(T obj, int delta)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      */
incrementAndGet(T obj)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      */
decrementAndGet(T obj)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      */
addAndGet(T obj, int delta)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      */
getAndUpdate(T obj, IntUnaryOperator updateFunction)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      */
updateAndGet(T obj, IntUnaryOperator updateFunction)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      */
getAndAccumulate(T obj, int x, IntBinaryOperator accumulatorFunction)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      */
accumulateAndGet(T obj, int x, IntBinaryOperator accumulatorFunction)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 final 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         /**
373          * if field is protected, the subclass constructing updater, else
374          * the same as tclass
375          */
376         private final Class<?> cclass;
377         /** class holding the field */
378         private final Class<T> tclass;
379 
AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, final String fieldName, final Class<?> caller)380         AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
381                                       final String fieldName,
382                                       final Class<?> caller) {
383             final Field field;
384             final int modifiers;
385             try {
386                 // BEGIN Android-changed: Skip privilege escalation which is a noop on Android.
387                 /*
388                 field = AccessController.doPrivileged(
389                     new PrivilegedExceptionAction<Field>() {
390                         public Field run() throws NoSuchFieldException {
391                             return tclass.getDeclaredField(fieldName);
392                         }
393                     });
394                 */
395                 field = tclass.getDeclaredField(fieldName);
396                 // END Android-changed: Skip privilege escalation which is a noop on Android.
397                 modifiers = field.getModifiers();
398                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
399                     caller, tclass, null, modifiers);
400                 // BEGIN Android-removed: Skip checkPackageAccess which is a noop on Android.
401                 /*
402                 ClassLoader cl = tclass.getClassLoader();
403                 ClassLoader ccl = caller.getClassLoader();
404                 if ((ccl != null) && (ccl != cl) &&
405                     ((cl == null) || !isAncestor(cl, ccl))) {
406                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
407                 }
408                 */
409                 // END Android-removed: Skip checkPackageAccess which is a noop on Android.
410             // BEGIN Android-removed: Skip privilege escalation which is a noop on Android.
411             /*
412             } catch (PrivilegedActionException pae) {
413                 throw new RuntimeException(pae.getException());
414             */
415             // END Android-removed: Skip privilege escalation which is a noop on Android.
416             } catch (Exception ex) {
417                 throw new RuntimeException(ex);
418             }
419 
420             if (field.getType() != int.class)
421                 throw new IllegalArgumentException("Must be integer type");
422 
423             if (!Modifier.isVolatile(modifiers))
424                 throw new IllegalArgumentException("Must be volatile type");
425 
426             this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
427             this.tclass = tclass;
428             this.offset = U.objectFieldOffset(field);
429         }
430 
431         // BEGIN Android-removed: isAncestor()'s only usage was removed above.
432         /*
433         /**
434          * Returns true if the second classloader can be found in the first
435          * classloader's delegation chain.
436          * Equivalent to the inaccessible: first.isAncestor(second).
437          *
438         private static boolean isAncestor(ClassLoader first, ClassLoader second) {
439             ClassLoader acl = first;
440             do {
441                 acl = acl.getParent();
442                 if (second == acl) {
443                     return true;
444                 }
445             } while (acl != null);
446             return false;
447         }
448         */
449         // END Android-removed: isAncestor()'s only usage was removed above.
450 
451         /**
452          * Checks that target argument is instance of cclass.  On
453          * failure, throws cause.
454          */
accessCheck(T obj)455         private final void accessCheck(T obj) {
456             if (!cclass.isInstance(obj))
457                 throwAccessCheckException(obj);
458         }
459 
460         /**
461          * Throws access exception if accessCheck failed due to
462          * protected access, else ClassCastException.
463          */
throwAccessCheckException(T obj)464         private final void throwAccessCheckException(T obj) {
465             if (cclass == tclass)
466                 throw new ClassCastException();
467             else
468                 throw new RuntimeException(
469                     new IllegalAccessException(
470                         "Class " +
471                         cclass.getName() +
472                         " can not access a protected member of class " +
473                         tclass.getName() +
474                         " using an instance of " +
475                         obj.getClass().getName()));
476         }
477 
compareAndSet(T obj, int expect, int update)478         public final boolean compareAndSet(T obj, int expect, int update) {
479             accessCheck(obj);
480             return U.compareAndSwapInt(obj, offset, expect, update);
481         }
482 
weakCompareAndSet(T obj, int expect, int update)483         public final boolean weakCompareAndSet(T obj, int expect, int update) {
484             accessCheck(obj);
485             return U.compareAndSwapInt(obj, offset, expect, update);
486         }
487 
set(T obj, int newValue)488         public final void set(T obj, int newValue) {
489             accessCheck(obj);
490             U.putIntVolatile(obj, offset, newValue);
491         }
492 
lazySet(T obj, int newValue)493         public final void lazySet(T obj, int newValue) {
494             accessCheck(obj);
495             U.putOrderedInt(obj, offset, newValue);
496         }
497 
get(T obj)498         public final int get(T obj) {
499             accessCheck(obj);
500             return U.getIntVolatile(obj, offset);
501         }
502 
getAndSet(T obj, int newValue)503         public final int getAndSet(T obj, int newValue) {
504             accessCheck(obj);
505             return U.getAndSetInt(obj, offset, newValue);
506         }
507 
getAndAdd(T obj, int delta)508         public final int getAndAdd(T obj, int delta) {
509             accessCheck(obj);
510             return U.getAndAddInt(obj, offset, delta);
511         }
512 
getAndIncrement(T obj)513         public final int getAndIncrement(T obj) {
514             return getAndAdd(obj, 1);
515         }
516 
getAndDecrement(T obj)517         public final int getAndDecrement(T obj) {
518             return getAndAdd(obj, -1);
519         }
520 
incrementAndGet(T obj)521         public final int incrementAndGet(T obj) {
522             return getAndAdd(obj, 1) + 1;
523         }
524 
decrementAndGet(T obj)525         public final int decrementAndGet(T obj) {
526             return getAndAdd(obj, -1) - 1;
527         }
528 
addAndGet(T obj, int delta)529         public final int addAndGet(T obj, int delta) {
530             return getAndAdd(obj, delta) + delta;
531         }
532 
533     }
534 }
535