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
36package java.util.concurrent.atomic;
37
38import java.lang.reflect.Field;
39import java.lang.reflect.Modifier;
40import java.security.AccessController;
41import java.security.PrivilegedActionException;
42import java.security.PrivilegedExceptionAction;
43import java.util.Objects;
44import java.util.function.IntBinaryOperator;
45import java.util.function.IntUnaryOperator;
46import jdk.internal.misc.Unsafe;
47import jdk.internal.reflect.CallerSensitive;
48import jdk.internal.reflect.Reflection;
49import 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 */
73public 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 true} if 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 true} if 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