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