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