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
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      */

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 trueif successful
114      */

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 trueif successful
132      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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      */

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
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                 field = AccessController.doPrivileged(
396                     new PrivilegedExceptionAction<Field>() {
397                         public Field run() throws NoSuchFieldException {
398                             return tclass.getDeclaredField(fieldName);
399                         }
400                     });
401                 modifiers = field.getModifiers();
402                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
403                     caller, tclass, null, modifiers);
404                 ClassLoader cl = tclass.getClassLoader();
405                 ClassLoader ccl = caller.getClassLoader();
406                 if ((ccl != null) && (ccl != cl) &&
407                     ((cl == null) || !isAncestor(cl, ccl))) {
408                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
409                 }
410             } catch (PrivilegedActionException pae) {
411                 throw new RuntimeException(pae.getException());
412             } catch (Exception ex) {
413                 throw new RuntimeException(ex);
414             }
415
416             if (field.getType() != int.class)
417                 throw new IllegalArgumentException("Must be integer type");
418
419             if (!Modifier.isVolatile(modifiers))
420                 throw new IllegalArgumentException("Must be volatile type");
421
422             // Access to protected field members is restricted to receivers only
423             // of the accessing class, or one of its subclasses, and the
424             // accessing class must in turn be a subclass (or package sibling)
425             // of the protected member's defining class.
426             // If the updater refers to a protected field of a declaring class
427             // outside the current package, the receiver argument will be
428             // narrowed to the type of the accessing class.
429             this.cclass = (Modifier.isProtected(modifiers) &&
430                            tclass.isAssignableFrom(caller) &&
431                            !isSamePackage(tclass, caller))
432                           ? caller : tclass;
433             this.tclass = tclass;
434             this.offset = U.objectFieldOffset(field);
435         }
436
437         /**
438          * Returns true if the second classloader can be found in the first
439          * classloader's delegation chain.
440          * Equivalent to the inaccessible: first.isAncestor(second).
441          */

442         private static boolean isAncestor(ClassLoader first, ClassLoader second) {
443             ClassLoader acl = first;
444             do {
445                 acl = acl.getParent();
446                 if (second == acl) {
447                     return true;
448                 }
449             } while (acl != null);
450             return false;
451         }
452
453         /**
454          * Returns true if the two classes have the same class loader and
455          * package qualifier
456          */

457         private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
458             return class1.getClassLoader() == class2.getClassLoader()
459                    && Objects.equals(class1.getPackageName(), class2.getPackageName());
460         }
461
462         /**
463          * Checks that target argument is instance of cclass.  On
464          * failure, throws cause.
465          */

466         private final void accessCheck(T obj) {
467             if (!cclass.isInstance(obj))
468                 throwAccessCheckException(obj);
469         }
470
471         /**
472          * Throws access exception if accessCheck failed due to
473          * protected access, else ClassCastException.
474          */

475         private final void throwAccessCheckException(T obj) {
476             if (cclass == tclass)
477                 throw new ClassCastException();
478             else
479                 throw new RuntimeException(
480                     new IllegalAccessException(
481                         "Class " +
482                         cclass.getName() +
483                         " can not access a protected member of class " +
484                         tclass.getName() +
485                         " using an instance of " +
486                         obj.getClass().getName()));
487         }
488
489         public final boolean compareAndSet(T obj, int expect, int update) {
490             accessCheck(obj);
491             return U.compareAndSetInt(obj, offset, expect, update);
492         }
493
494         public final boolean weakCompareAndSet(T obj, int expect, int update) {
495             accessCheck(obj);
496             return U.compareAndSetInt(obj, offset, expect, update);
497         }
498
499         public final void set(T obj, int newValue) {
500             accessCheck(obj);
501             U.putIntVolatile(obj, offset, newValue);
502         }
503
504         public final void lazySet(T obj, int newValue) {
505             accessCheck(obj);
506             U.putIntRelease(obj, offset, newValue);
507         }
508
509         public final int get(T obj) {
510             accessCheck(obj);
511             return U.getIntVolatile(obj, offset);
512         }
513
514         public final int getAndSet(T obj, int newValue) {
515             accessCheck(obj);
516             return U.getAndSetInt(obj, offset, newValue);
517         }
518
519         public final int getAndAdd(T obj, int delta) {
520             accessCheck(obj);
521             return U.getAndAddInt(obj, offset, delta);
522         }
523
524         public final int getAndIncrement(T obj) {
525             return getAndAdd(obj, 1);
526         }
527
528         public final int getAndDecrement(T obj) {
529             return getAndAdd(obj, -1);
530         }
531
532         public final int incrementAndGet(T obj) {
533             return getAndAdd(obj, 1) + 1;
534         }
535
536         public final int decrementAndGet(T obj) {
537             return getAndAdd(obj, -1) - 1;
538         }
539
540         public final int addAndGet(T obj, int delta) {
541             return getAndAdd(obj, delta) + delta;
542         }
543
544     }
545 }
546