AtomicLongFieldUpdater.java revision 29957558cf0db700bfaae360a80c42dc3871d0e5
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.LongBinaryOperator;
45import java.util.function.LongUnaryOperator;
46import sun.reflect.CallerSensitive;
47import sun.reflect.Reflection;
48
49/**
50 * A reflection-based utility that enables atomic updates to
51 * designated {@code volatile long} 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 AtomicLongFieldUpdater<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 long 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> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
86                                                           String fieldName) {
87      Class<?> caller = VMStack.getStackClass1(); // android-changed
88        if (AtomicLong.VM_SUPPORTS_LONG_CAS)
89            return new CASUpdater<U>(tclass, fieldName, caller);
90        else
91            return new LockedUpdater<U>(tclass, fieldName, caller);
92    }
93
94    /**
95     * Protected do-nothing constructor for use by subclasses.
96     */
97    protected AtomicLongFieldUpdater() {
98    }
99
100    /**
101     * Atomically sets the field of the given object managed by this updater
102     * to the given updated value if the current value {@code ==} the
103     * expected value. This method is guaranteed to be atomic with respect to
104     * other calls to {@code compareAndSet} and {@code set}, but not
105     * necessarily with respect to other changes in the field.
106     *
107     * @param obj An object whose field to conditionally set
108     * @param expect the expected value
109     * @param update the new value
110     * @return {@code true} if successful
111     * @throws ClassCastException if {@code obj} is not an instance
112     * of the class possessing the field established in the constructor
113     */
114    public abstract boolean compareAndSet(T obj, long expect, long 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><a href="package-summary.html#weakCompareAndSet">May fail
124     * spuriously and does not provide ordering guarantees</a>, so is
125     * only rarely an appropriate 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     * @throws ClassCastException if {@code obj} is not an instance
132     * of the class possessing the field established in the constructor
133     */
134    public abstract boolean weakCompareAndSet(T obj, long expect, long update);
135
136    /**
137     * Sets the field of the given object managed by this updater to the
138     * given updated value. This operation is guaranteed to act as a volatile
139     * store with respect to subsequent invocations of {@code compareAndSet}.
140     *
141     * @param obj An object whose field to set
142     * @param newValue the new value
143     */
144    public abstract void set(T obj, long newValue);
145
146    /**
147     * Eventually sets the field of the given object managed by this
148     * updater to the given updated value.
149     *
150     * @param obj An object whose field to set
151     * @param newValue the new value
152     * @since 1.6
153     */
154    public abstract void lazySet(T obj, long newValue);
155
156    /**
157     * Gets the current value held in the field of the given object managed
158     * by this updater.
159     *
160     * @param obj An object whose field to get
161     * @return the current value
162     */
163    public abstract long get(T obj);
164
165    /**
166     * Atomically sets the field of the given object managed by this updater
167     * to the given value and returns the old value.
168     *
169     * @param obj An object whose field to get and set
170     * @param newValue the new value
171     * @return the previous value
172     */
173    public long getAndSet(T obj, long newValue) {
174        long prev;
175        do {
176            prev = get(obj);
177        } while (!compareAndSet(obj, prev, newValue));
178        return prev;
179    }
180
181    /**
182     * Atomically increments by one the current value of the field of the
183     * given object managed by this updater.
184     *
185     * @param obj An object whose field to get and set
186     * @return the previous value
187     */
188    public long getAndIncrement(T obj) {
189        long prev, next;
190        do {
191            prev = get(obj);
192            next = prev + 1;
193        } while (!compareAndSet(obj, prev, next));
194        return prev;
195    }
196
197    /**
198     * Atomically decrements by one the current value of the field of the
199     * given object managed by this updater.
200     *
201     * @param obj An object whose field to get and set
202     * @return the previous value
203     */
204    public long getAndDecrement(T obj) {
205        long prev, next;
206        do {
207            prev = get(obj);
208            next = prev - 1;
209        } while (!compareAndSet(obj, prev, next));
210        return prev;
211    }
212
213    /**
214     * Atomically adds the given value to the current value of the field of
215     * the given object managed by this updater.
216     *
217     * @param obj An object whose field to get and set
218     * @param delta the value to add
219     * @return the previous value
220     */
221    public long getAndAdd(T obj, long delta) {
222        long prev, next;
223        do {
224            prev = get(obj);
225            next = prev + delta;
226        } while (!compareAndSet(obj, prev, next));
227        return prev;
228    }
229
230    /**
231     * Atomically increments by one the current value of the field of the
232     * given object managed by this updater.
233     *
234     * @param obj An object whose field to get and set
235     * @return the updated value
236     */
237    public long incrementAndGet(T obj) {
238        long prev, next;
239        do {
240            prev = get(obj);
241            next = prev + 1;
242        } while (!compareAndSet(obj, prev, next));
243        return next;
244    }
245
246    /**
247     * Atomically decrements by one the current value of the field of the
248     * given object managed by this updater.
249     *
250     * @param obj An object whose field to get and set
251     * @return the updated value
252     */
253    public long decrementAndGet(T obj) {
254        long prev, next;
255        do {
256            prev = get(obj);
257            next = prev - 1;
258        } while (!compareAndSet(obj, prev, next));
259        return next;
260    }
261
262    /**
263     * Atomically adds the given value to the current value of the field of
264     * the given object managed by this updater.
265     *
266     * @param obj An object whose field to get and set
267     * @param delta the value to add
268     * @return the updated value
269     */
270    public long addAndGet(T obj, long delta) {
271        long prev, next;
272        do {
273            prev = get(obj);
274            next = prev + delta;
275        } while (!compareAndSet(obj, prev, next));
276        return next;
277    }
278
279    /**
280     * Atomically updates the field of the given object managed by this updater
281     * with the results of applying the given function, returning the previous
282     * value. The function should be side-effect-free, since it may be
283     * re-applied when attempted 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     */
290    public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
291        long prev, next;
292        do {
293            prev = get(obj);
294            next = updateFunction.applyAsLong(prev);
295        } while (!compareAndSet(obj, prev, next));
296        return prev;
297    }
298
299    /**
300     * Atomically updates the field of the given object managed by this updater
301     * with the results of applying the given function, returning the updated
302     * value. The function should be side-effect-free, since it may be
303     * re-applied when attempted updates fail due to contention among threads.
304     *
305     * @param obj An object whose field to get and set
306     * @param updateFunction a side-effect-free function
307     * @return the updated value
308     * @since 1.8
309     */
310    public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
311        long prev, next;
312        do {
313            prev = get(obj);
314            next = updateFunction.applyAsLong(prev);
315        } while (!compareAndSet(obj, prev, next));
316        return next;
317    }
318
319    /**
320     * Atomically updates the field of the given object managed by this
321     * updater with the results of applying the given function to the
322     * current and given values, returning the previous value. The
323     * function should be side-effect-free, since it may be re-applied
324     * when attempted updates fail due to contention among threads.  The
325     * function is applied with the current value as its first argument,
326     * and the given update as the second argument.
327     *
328     * @param obj An object whose field to get and set
329     * @param x the update value
330     * @param accumulatorFunction a side-effect-free function of two arguments
331     * @return the previous value
332     * @since 1.8
333     */
334    public final long getAndAccumulate(T obj, long x,
335                                       LongBinaryOperator accumulatorFunction) {
336        long prev, next;
337        do {
338            prev = get(obj);
339            next = accumulatorFunction.applyAsLong(prev, x);
340        } while (!compareAndSet(obj, prev, next));
341        return prev;
342    }
343
344    /**
345     * Atomically updates the field of the given object managed by this
346     * updater with the results of applying the given function to the
347     * current and given values, returning the updated value. The
348     * function should be side-effect-free, since it may be re-applied
349     * when attempted updates fail due to contention among threads.  The
350     * function is applied with the current value as its first argument,
351     * and the given update as the second argument.
352     *
353     * @param obj An object whose field to get and set
354     * @param x the update value
355     * @param accumulatorFunction a side-effect-free function of two arguments
356     * @return the updated value
357     * @since 1.8
358     */
359    public final long accumulateAndGet(T obj, long x,
360                                       LongBinaryOperator accumulatorFunction) {
361        long prev, next;
362        do {
363            prev = get(obj);
364            next = accumulatorFunction.applyAsLong(prev, x);
365        } while (!compareAndSet(obj, prev, next));
366        return next;
367    }
368
369    private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
370        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
371        private final long offset;
372        /**
373         * if field is protected, the subclass constructing updater, else
374         * the same as tclass
375         */
376        private final Class<?> cclass;
377        /** class holding the field */
378        private final Class<T> tclass;
379
380        CASUpdater(final Class<T> tclass, final String fieldName,
381                   final Class<?> caller) {
382            final Field field;
383            final int modifiers;
384            try {
385                field = tclass.getDeclaredField(fieldName); // android-changed
386                modifiers = field.getModifiers();
387                // BEGIN android-removed
388                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
389                //     caller, tclass, null, modifiers);
390                // ClassLoader cl = tclass.getClassLoader();
391                // ClassLoader ccl = caller.getClassLoader();
392                // if ((ccl != null) && (ccl != cl) &&
393                //     ((cl == null) || !isAncestor(cl, ccl))) {
394                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
395                // }
396                // END android-removed
397            // BEGIN android-removed
398            // } catch (PrivilegedActionException pae) {
399            //     throw new RuntimeException(pae.getException());
400            // END android-removed
401            } catch (Exception ex) {
402                throw new RuntimeException(ex);
403            }
404
405            if (field.getType() != long.class)
406                throw new IllegalArgumentException("Must be long type");
407
408            if (!Modifier.isVolatile(modifiers))
409                throw new IllegalArgumentException("Must be volatile type");
410
411            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
412            this.tclass = tclass;
413            this.offset = U.objectFieldOffset(field);
414        }
415
416        /**
417         * Checks that target argument is instance of cclass.  On
418         * failure, throws cause.
419         */
420        private final void accessCheck(T obj) {
421            if (!cclass.isInstance(obj))
422                throwAccessCheckException(obj);
423        }
424
425        /**
426         * Throws access exception if accessCheck failed due to
427         * protected access, else ClassCastException.
428         */
429        private final void throwAccessCheckException(T obj) {
430            if (cclass == tclass)
431                throw new ClassCastException();
432            else
433                throw new RuntimeException(
434                    new IllegalAccessException(
435                        "Class " +
436                        cclass.getName() +
437                        " can not access a protected member of class " +
438                        tclass.getName() +
439                        " using an instance of " +
440                        obj.getClass().getName()));
441        }
442
443        public final boolean compareAndSet(T obj, long expect, long update) {
444            accessCheck(obj);
445            return U.compareAndSwapLong(obj, offset, expect, update);
446        }
447
448        public final boolean weakCompareAndSet(T obj, long expect, long update) {
449            accessCheck(obj);
450            return U.compareAndSwapLong(obj, offset, expect, update);
451        }
452
453        public final void set(T obj, long newValue) {
454            accessCheck(obj);
455            U.putLongVolatile(obj, offset, newValue);
456        }
457
458        public final void lazySet(T obj, long newValue) {
459            accessCheck(obj);
460            U.putOrderedLong(obj, offset, newValue);
461        }
462
463        public final long get(T obj) {
464            accessCheck(obj);
465            return U.getLongVolatile(obj, offset);
466        }
467
468        public final long getAndSet(T obj, long newValue) {
469            accessCheck(obj);
470            return U.getAndSetLong(obj, offset, newValue);
471        }
472
473        public final long getAndAdd(T obj, long delta) {
474            accessCheck(obj);
475            return U.getAndAddLong(obj, offset, delta);
476        }
477
478        public final long getAndIncrement(T obj) {
479            return getAndAdd(obj, 1);
480        }
481
482        public final long getAndDecrement(T obj) {
483            return getAndAdd(obj, -1);
484        }
485
486        public final long incrementAndGet(T obj) {
487            return getAndAdd(obj, 1) + 1;
488        }
489
490        public final long decrementAndGet(T obj) {
491            return getAndAdd(obj, -1) - 1;
492        }
493
494        public final long addAndGet(T obj, long delta) {
495            return getAndAdd(obj, delta) + delta;
496        }
497    }
498
499    private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
500        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
501        private final long offset;
502        /**
503         * if field is protected, the subclass constructing updater, else
504         * the same as tclass
505         */
506        private final Class<?> cclass;
507        /** class holding the field */
508        private final Class<T> tclass;
509
510        LockedUpdater(final Class<T> tclass, final String fieldName,
511                      final Class<?> caller) {
512            Field field = null;
513            int modifiers = 0;
514            try {
515                field = tclass.getDeclaredField(fieldName); // android-changed
516                modifiers = field.getModifiers();
517                // BEGIN android-removed
518                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
519                //     caller, tclass, null, modifiers);
520                // ClassLoader cl = tclass.getClassLoader();
521                // ClassLoader ccl = caller.getClassLoader();
522                // if ((ccl != null) && (ccl != cl) &&
523                //     ((cl == null) || !isAncestor(cl, ccl))) {
524                //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
525                // }
526                // END android-removed
527            // BEGIN android-removed
528            // } catch (PrivilegedActionException pae) {
529            //     throw new RuntimeException(pae.getException());
530            // END android-removed
531            } catch (Exception ex) {
532                throw new RuntimeException(ex);
533            }
534
535            if (field.getType() != long.class)
536                throw new IllegalArgumentException("Must be long type");
537
538            if (!Modifier.isVolatile(modifiers))
539                throw new IllegalArgumentException("Must be volatile type");
540
541            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
542            this.tclass = tclass;
543            this.offset = U.objectFieldOffset(field);
544        }
545
546        /**
547         * Checks that target argument is instance of cclass.  On
548         * failure, throws cause.
549         */
550        private final void accessCheck(T obj) {
551            if (!cclass.isInstance(obj))
552                throw accessCheckException(obj);
553        }
554
555        /**
556         * Returns access exception if accessCheck failed due to
557         * protected access, else ClassCastException.
558         */
559        private final RuntimeException accessCheckException(T obj) {
560            if (cclass == tclass)
561                return new ClassCastException();
562            else
563                return new RuntimeException(
564                    new IllegalAccessException(
565                        "Class " +
566                        cclass.getName() +
567                        " can not access a protected member of class " +
568                        tclass.getName() +
569                        " using an instance of " +
570                        obj.getClass().getName()));
571        }
572
573        public final boolean compareAndSet(T obj, long expect, long update) {
574            accessCheck(obj);
575            synchronized (this) {
576                long v = U.getLong(obj, offset);
577                if (v != expect)
578                    return false;
579                U.putLong(obj, offset, update);
580                return true;
581            }
582        }
583
584        public final boolean weakCompareAndSet(T obj, long expect, long update) {
585            return compareAndSet(obj, expect, update);
586        }
587
588        public final void set(T obj, long newValue) {
589            accessCheck(obj);
590            synchronized (this) {
591                U.putLong(obj, offset, newValue);
592            }
593        }
594
595        public final void lazySet(T obj, long newValue) {
596            set(obj, newValue);
597        }
598
599        public final long get(T obj) {
600            accessCheck(obj);
601            synchronized (this) {
602                return U.getLong(obj, offset);
603            }
604        }
605    }
606
607    // BEGIN android-removed
608    // /**
609    //  * Returns true if the second classloader can be found in the first
610    //  * classloader's delegation chain.
611    //  * Equivalent to the inaccessible: first.isAncestor(second).
612    //  */
613    // static boolean isAncestor(ClassLoader first, ClassLoader second) {
614    //     ClassLoader acl = first;
615    //     do {
616    //         acl = acl.getParent();
617    //         if (second == acl) {
618    //             return true;
619    //         }
620    //     } while (acl != null);
621    //     return false;
622    // }
623    // END android-removed
624}
625