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