• 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.Objects;
44 import java.util.function.IntBinaryOperator;
45 import java.util.function.IntUnaryOperator;
46 import jdk.internal.misc.Unsafe;
47 import jdk.internal.reflect.CallerSensitive;
48 import jdk.internal.reflect.Reflection;
49 import java.lang.invoke.VarHandle;
50 
51 /**
52  * A reflection-based utility that enables atomic updates to
53  * designated {@code volatile int} fields of designated classes.
54  * This class is designed for use in atomic data structures in which
55  * several fields of the same node are independently subject to atomic
56  * updates.
57  *
58  * <p>Note that the guarantees of the {@code compareAndSet}
59  * method in this class are weaker than in other atomic classes.
60  * Because this class cannot ensure that all uses of the field
61  * are appropriate for purposes of atomic access, it can
62  * guarantee atomicity only with respect to other invocations of
63  * {@code compareAndSet} and {@code set} on the same updater.
64  *
65  * <p>Object arguments for parameters of type {@code T} that are not
66  * instances of the class passed to {@link #newUpdater} will result in
67  * a {@link ClassCastException} being thrown.
68  *
69  * @since 1.5
70  * @author Doug Lea
71  * @param <T> The type of the object holding the updatable field
72  */
73 public abstract class AtomicIntegerFieldUpdater<T> {
74     /**
75      * Creates and returns an updater for objects with the given field.
76      * The Class argument is needed to check that reflective types and
77      * generic types match.
78      *
79      * @param tclass the class of the objects holding the field
80      * @param fieldName the name of the field to be updated
81      * @param <U> the type of instances of tclass
82      * @return the updater
83      * @throws IllegalArgumentException if the field is not a
84      * volatile integer type
85      * @throws RuntimeException with a nested reflection-based
86      * exception if the class does not hold field or is the wrong type,
87      * or the field is inaccessible to the caller according to Java language
88      * access control
89      */
90     @CallerSensitive
newUpdater(Class<U> tclass, String fieldName)91     public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
92                                                               String fieldName) {
93         return new AtomicIntegerFieldUpdaterImpl<U>
94             (tclass, fieldName, Reflection.getCallerClass());
95     }
96 
97     /**
98      * Protected do-nothing constructor for use by subclasses.
99      */
AtomicIntegerFieldUpdater()100     protected AtomicIntegerFieldUpdater() {
101     }
102 
103     /**
104      * Atomically sets the field of the given object managed by this updater
105      * to the given updated value if the current value {@code ==} the
106      * expected value. This method is guaranteed to be atomic with respect to
107      * other calls to {@code compareAndSet} and {@code set}, but not
108      * necessarily with respect to other changes in the field.
109      *
110      * @param obj An object whose field to conditionally set
111      * @param expect the expected value
112      * @param update the new value
113      * @return {@code true} if successful
114      */
compareAndSet(T obj, int expect, int update)115     public abstract boolean compareAndSet(T obj, int expect, int update);
116 
117     /**
118      * Atomically sets the field of the given object managed by this updater
119      * to the given updated value if the current value {@code ==} the
120      * expected value. This method is guaranteed to be atomic with respect to
121      * other calls to {@code compareAndSet} and {@code set}, but not
122      * necessarily with respect to other changes in the field.
123      *
124      * <p><a href="package-summary.html#weakCompareAndSet">May fail
125      * spuriously and does not provide ordering guarantees</a>, so is
126      * only rarely an appropriate alternative to {@code compareAndSet}.
127      *
128      * @param obj An object whose field to conditionally set
129      * @param expect the expected value
130      * @param update the new value
131      * @return {@code true} if successful
132      */
weakCompareAndSet(T obj, int expect, int update)133     public abstract boolean weakCompareAndSet(T obj, int expect, int update);
134 
135     /**
136      * Sets the field of the given object managed by this updater to the
137      * given updated value. This operation is guaranteed to act as a volatile
138      * store with respect to subsequent invocations of {@code compareAndSet}.
139      *
140      * @param obj An object whose field to set
141      * @param newValue the new value
142      */
set(T obj, int newValue)143     public abstract void set(T obj, int newValue);
144 
145     /**
146      * Eventually sets the field of the given object managed by this
147      * updater to the given updated value.
148      *
149      * @param obj An object whose field to set
150      * @param newValue the new value
151      * @since 1.6
152      */
lazySet(T obj, int newValue)153     public abstract void lazySet(T obj, int newValue);
154 
155     /**
156      * Returns the current value held in the field of the given object
157      * managed by this updater.
158      *
159      * @param obj An object whose field to get
160      * @return the current value
161      */
get(T obj)162     public abstract int get(T obj);
163 
164     /**
165      * Atomically sets the field of the given object managed by this updater
166      * to the given value and returns the old value.
167      *
168      * @param obj An object whose field to get and set
169      * @param newValue the new value
170      * @return the previous value
171      */
getAndSet(T obj, int newValue)172     public int getAndSet(T obj, int newValue) {
173         int prev;
174         do {
175             prev = get(obj);
176         } while (!compareAndSet(obj, prev, newValue));
177         return prev;
178     }
179 
180     /**
181      * Atomically increments by one the current value of the field of the
182      * given object managed by this updater.
183      *
184      * @param obj An object whose field to get and set
185      * @return the previous value
186      */
getAndIncrement(T obj)187     public int getAndIncrement(T obj) {
188         int prev, next;
189         do {
190             prev = get(obj);
191             next = prev + 1;
192         } while (!compareAndSet(obj, prev, next));
193         return prev;
194     }
195 
196     /**
197      * Atomically decrements by one the current value of the field of the
198      * given object managed by this updater.
199      *
200      * @param obj An object whose field to get and set
201      * @return the previous value
202      */
getAndDecrement(T obj)203     public int getAndDecrement(T obj) {
204         int prev, next;
205         do {
206             prev = get(obj);
207             next = prev - 1;
208         } while (!compareAndSet(obj, prev, next));
209         return prev;
210     }
211 
212     /**
213      * Atomically adds the given value to the current value of the field of
214      * the given object managed by this updater.
215      *
216      * @param obj An object whose field to get and set
217      * @param delta the value to add
218      * @return the previous value
219      */
getAndAdd(T obj, int delta)220     public int getAndAdd(T obj, int delta) {
221         int prev, next;
222         do {
223             prev = get(obj);
224             next = prev + delta;
225         } while (!compareAndSet(obj, prev, next));
226         return prev;
227     }
228 
229     /**
230      * Atomically increments by one the current value of the field of the
231      * given object managed by this updater.
232      *
233      * @param obj An object whose field to get and set
234      * @return the updated value
235      */
incrementAndGet(T obj)236     public int incrementAndGet(T obj) {
237         int prev, next;
238         do {
239             prev = get(obj);
240             next = prev + 1;
241         } while (!compareAndSet(obj, prev, next));
242         return next;
243     }
244 
245     /**
246      * Atomically decrements by one the current value of the field of the
247      * given object managed by this updater.
248      *
249      * @param obj An object whose field to get and set
250      * @return the updated value
251      */
decrementAndGet(T obj)252     public int decrementAndGet(T obj) {
253         int prev, next;
254         do {
255             prev = get(obj);
256             next = prev - 1;
257         } while (!compareAndSet(obj, prev, next));
258         return next;
259     }
260 
261     /**
262      * Atomically adds the given value to the current value of the field of
263      * the given object managed by this updater.
264      *
265      * @param obj An object whose field to get and set
266      * @param delta the value to add
267      * @return the updated value
268      */
addAndGet(T obj, int delta)269     public int addAndGet(T obj, int delta) {
270         int prev, next;
271         do {
272             prev = get(obj);
273             next = prev + delta;
274         } while (!compareAndSet(obj, prev, next));
275         return next;
276     }
277 
278     /**
279      * Atomically updates (with memory effects as specified by {@link
280      * VarHandle#compareAndSet}) the field of the given object managed
281      * by this updater with the results of applying the given
282      * function, returning the previous value. The function should be
283      * side-effect-free, since it may be re-applied when attempted
284      * updates fail due to contention among threads.
285      *
286      * @param obj An object whose field to get and set
287      * @param updateFunction a side-effect-free function
288      * @return the previous value
289      * @since 1.8
290      */
getAndUpdate(T obj, IntUnaryOperator updateFunction)291     public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
292         int prev, next;
293         do {
294             prev = get(obj);
295             next = updateFunction.applyAsInt(prev);
296         } while (!compareAndSet(obj, prev, next));
297         return prev;
298     }
299 
300     /**
301      * Atomically updates (with memory effects as specified by {@link
302      * VarHandle#compareAndSet}) the field of the given object managed
303      * by this updater with the results of applying the given
304      * function, returning the updated value. The function should be
305      * side-effect-free, since it may be re-applied when attempted
306      * updates fail due to contention among threads.
307      *
308      * @param obj An object whose field to get and set
309      * @param updateFunction a side-effect-free function
310      * @return the updated value
311      * @since 1.8
312      */
updateAndGet(T obj, IntUnaryOperator updateFunction)313     public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
314         int prev, next;
315         do {
316             prev = get(obj);
317             next = updateFunction.applyAsInt(prev);
318         } while (!compareAndSet(obj, prev, next));
319         return next;
320     }
321 
322     /**
323      * Atomically updates (with memory effects as specified by {@link
324      * VarHandle#compareAndSet}) the field of the given object managed
325      * by this updater with the results of applying the given function
326      * to the current and given values, returning the previous value.
327      * The function should be side-effect-free, since it may be
328      * re-applied when attempted updates fail due to contention among
329      * threads.  The function is applied with the current value as its
330      * first argument, and the given update as the second argument.
331      *
332      * @param obj An object whose field to get and set
333      * @param x the update value
334      * @param accumulatorFunction a side-effect-free function of two arguments
335      * @return the previous value
336      * @since 1.8
337      */
getAndAccumulate(T obj, int x, IntBinaryOperator accumulatorFunction)338     public final int getAndAccumulate(T obj, int x,
339                                       IntBinaryOperator accumulatorFunction) {
340         int prev, next;
341         do {
342             prev = get(obj);
343             next = accumulatorFunction.applyAsInt(prev, x);
344         } while (!compareAndSet(obj, prev, next));
345         return prev;
346     }
347 
348     /**
349      * Atomically updates (with memory effects as specified by {@link
350      * VarHandle#compareAndSet}) the field of the given object managed
351      * by this updater with the results of applying the given function
352      * to the current and given values, returning the updated value.
353      * The function should be side-effect-free, since it may be
354      * re-applied when attempted updates fail due to contention among
355      * threads.  The function is applied with the current value as its
356      * first argument, and the given update as the second argument.
357      *
358      * @param obj An object whose field to get and set
359      * @param x the update value
360      * @param accumulatorFunction a side-effect-free function of two arguments
361      * @return the updated value
362      * @since 1.8
363      */
accumulateAndGet(T obj, int x, IntBinaryOperator accumulatorFunction)364     public final int accumulateAndGet(T obj, int x,
365                                       IntBinaryOperator accumulatorFunction) {
366         int prev, next;
367         do {
368             prev = get(obj);
369             next = accumulatorFunction.applyAsInt(prev, x);
370         } while (!compareAndSet(obj, prev, next));
371         return next;
372     }
373 
374     /**
375      * Standard hotspot implementation using intrinsics.
376      */
377     private static final class AtomicIntegerFieldUpdaterImpl<T>
378         extends AtomicIntegerFieldUpdater<T> {
379         private static final Unsafe U = Unsafe.getUnsafe();
380         private final long offset;
381         /**
382          * if field is protected, the subclass constructing updater, else
383          * the same as tclass
384          */
385         private final Class<?> cclass;
386         /** class holding the field */
387         private final Class<T> tclass;
388 
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                    && Objects.equals(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