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