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 
36 package java.util.concurrent.atomic;
37 
38 import java.lang.reflect.Field;
39 import java.lang.reflect.Modifier;
40 import java.security.AccessController;
41 import java.security.PrivilegedActionException;
42 import java.security.PrivilegedExceptionAction;
43 import java.util.function.LongBinaryOperator;
44 import java.util.function.LongUnaryOperator;
45 import jdk.internal.misc.Unsafe;
46 import jdk.internal.reflect.CallerSensitive;
47 import jdk.internal.reflect.Reflection;
48 import java.lang.invoke.VarHandle;
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  */
72 public 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
newUpdater(Class<U> tclass, String fieldName)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      */
AtomicLongFieldUpdater()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      */
compareAndSet(T obj, long expect, long update)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>This operation may fail spuriously and does not provide
127      * ordering guarantees, so is only rarely an appropriate
128      * 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      */
weakCompareAndSet(T obj, long expect, long update)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      */
set(T obj, long newValue)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      */
lazySet(T obj, long newValue)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      */
get(T obj)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      */
getAndSet(T obj, long newValue)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      */
getAndIncrement(T obj)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      */
getAndDecrement(T obj)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      */
getAndAdd(T obj, long delta)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      */
incrementAndGet(T obj)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      */
decrementAndGet(T obj)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      */
addAndGet(T obj, long delta)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 (with memory effects as specified by {@link
282      * VarHandle#compareAndSet}) the field of the given object managed
283      * by this updater with the results of applying the given
284      * function, returning the previous value. The function should be
285      * side-effect-free, since it may be re-applied when attempted
286      * updates fail due to contention among threads.
287      *
288      * @param obj An object whose field to get and set
289      * @param updateFunction a side-effect-free function
290      * @return the previous value
291      * @since 1.8
292      */
getAndUpdate(T obj, LongUnaryOperator updateFunction)293     public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
294         long prev, next;
295         do {
296             prev = get(obj);
297             next = updateFunction.applyAsLong(prev);
298         } while (!compareAndSet(obj, prev, next));
299         return prev;
300     }
301 
302     /**
303      * Atomically updates (with memory effects as specified by {@link
304      * VarHandle#compareAndSet}) the field of the given object managed
305      * by this updater with the results of applying the given
306      * function, returning the updated value. The function should be
307      * side-effect-free, since it may be re-applied when attempted
308      * updates fail due to contention among threads.
309      *
310      * @param obj An object whose field to get and set
311      * @param updateFunction a side-effect-free function
312      * @return the updated value
313      * @since 1.8
314      */
updateAndGet(T obj, LongUnaryOperator updateFunction)315     public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
316         long prev, next;
317         do {
318             prev = get(obj);
319             next = updateFunction.applyAsLong(prev);
320         } while (!compareAndSet(obj, prev, next));
321         return next;
322     }
323 
324     /**
325      * Atomically updates (with memory effects as specified by {@link
326      * VarHandle#compareAndSet}) the field of the given object managed
327      * by this updater with the results of applying the given function
328      * to the current and given values, returning the previous value.
329      * The function should be side-effect-free, since it may be
330      * re-applied when attempted updates fail due to contention among
331      * threads.  The function is applied with the current value as its
332      * first argument, and the given update as the second argument.
333      *
334      * @param obj An object whose field to get and set
335      * @param x the update value
336      * @param accumulatorFunction a side-effect-free function of two arguments
337      * @return the previous value
338      * @since 1.8
339      */
getAndAccumulate(T obj, long x, LongBinaryOperator accumulatorFunction)340     public final long getAndAccumulate(T obj, long x,
341                                        LongBinaryOperator accumulatorFunction) {
342         long prev, next;
343         do {
344             prev = get(obj);
345             next = accumulatorFunction.applyAsLong(prev, x);
346         } while (!compareAndSet(obj, prev, next));
347         return prev;
348     }
349 
350     /**
351      * Atomically updates (with memory effects as specified by {@link
352      * VarHandle#compareAndSet}) the field of the given object managed
353      * by this updater with the results of applying the given function
354      * to the current and given values, returning the updated value.
355      * The function should be side-effect-free, since it may be
356      * re-applied when attempted updates fail due to contention among
357      * threads.  The function is applied with the current value as its
358      * first argument, and the given update as the second argument.
359      *
360      * @param obj An object whose field to get and set
361      * @param x the update value
362      * @param accumulatorFunction a side-effect-free function of two arguments
363      * @return the updated value
364      * @since 1.8
365      */
accumulateAndGet(T obj, long x, LongBinaryOperator accumulatorFunction)366     public final long accumulateAndGet(T obj, long x,
367                                        LongBinaryOperator accumulatorFunction) {
368         long prev, next;
369         do {
370             prev = get(obj);
371             next = accumulatorFunction.applyAsLong(prev, x);
372         } while (!compareAndSet(obj, prev, next));
373         return next;
374     }
375 
376     private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
377         private static final Unsafe U = Unsafe.getUnsafe();
378         private final long offset;
379         /**
380          * if field is protected, the subclass constructing updater, else
381          * the same as tclass
382          */
383         private final Class<?> cclass;
384         /** class holding the field */
385         private final Class<T> tclass;
386 
387         @SuppressWarnings("removal")
CASUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller)388         CASUpdater(final Class<T> tclass, final String fieldName,
389                    final Class<?> caller) {
390             final Field field;
391             final int modifiers;
392             try {
393                 // Android-changed: Skip privilege escalation which is a noop on Android.
394                 /*
395                 field = AccessController.doPrivileged(
396                     new PrivilegedExceptionAction<Field>() {
397                         public Field run() throws NoSuchFieldException {
398                             return tclass.getDeclaredField(fieldName);
399                         }
400                     });
401                 */
402                 field = tclass.getDeclaredField(fieldName);
403                 modifiers = field.getModifiers();
404                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
405                     caller, tclass, null, modifiers);
406                 // Android-removed: Skip checkPackageAccess which is a noop on Android.
407                 /*
408                 ClassLoader cl = tclass.getClassLoader();
409                 ClassLoader ccl = caller.getClassLoader();
410                 if ((ccl != null) && (ccl != cl) &&
411                     ((cl == null) || !isAncestor(cl, ccl))) {
412                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
413                 }
414                 */
415             // Android-removed: Skip privilege escalation which is a noop on Android.
416             /*
417             } catch (PrivilegedActionException pae) {
418                 throw new RuntimeException(pae.getException());
419             */
420             } catch (Exception ex) {
421                 throw new RuntimeException(ex);
422             }
423 
424             if (field.getType() != long.class)
425                 throw new IllegalArgumentException("Must be long type");
426 
427             if (!Modifier.isVolatile(modifiers))
428                 throw new IllegalArgumentException("Must be volatile type");
429 
430             // Access to protected field members is restricted to receivers only
431             // of the accessing class, or one of its subclasses, and the
432             // accessing class must in turn be a subclass (or package sibling)
433             // of the protected member's defining class.
434             // If the updater refers to a protected field of a declaring class
435             // outside the current package, the receiver argument will be
436             // narrowed to the type of the accessing class.
437             this.cclass = (Modifier.isProtected(modifiers) &&
438                            tclass.isAssignableFrom(caller) &&
439                            !isSamePackage(tclass, caller))
440                           ? caller : tclass;
441             this.tclass = tclass;
442             this.offset = U.objectFieldOffset(field);
443         }
444 
445         /**
446          * Checks that target argument is instance of cclass.  On
447          * failure, throws cause.
448          */
accessCheck(T obj)449         private final void accessCheck(T obj) {
450             if (!cclass.isInstance(obj))
451                 throwAccessCheckException(obj);
452         }
453 
454         /**
455          * Throws access exception if accessCheck failed due to
456          * protected access, else ClassCastException.
457          */
throwAccessCheckException(T obj)458         private final void throwAccessCheckException(T obj) {
459             if (cclass == tclass)
460                 throw new ClassCastException();
461             else
462                 throw new RuntimeException(
463                     new IllegalAccessException(
464                         "Class " +
465                         cclass.getName() +
466                         " can not access a protected member of class " +
467                         tclass.getName() +
468                         " using an instance of " +
469                         obj.getClass().getName()));
470         }
471 
compareAndSet(T obj, long expect, long update)472         public final boolean compareAndSet(T obj, long expect, long update) {
473             accessCheck(obj);
474             return U.compareAndSetLong(obj, offset, expect, update);
475         }
476 
weakCompareAndSet(T obj, long expect, long update)477         public final boolean weakCompareAndSet(T obj, long expect, long update) {
478             accessCheck(obj);
479             return U.compareAndSetLong(obj, offset, expect, update);
480         }
481 
set(T obj, long newValue)482         public final void set(T obj, long newValue) {
483             accessCheck(obj);
484             U.putLongVolatile(obj, offset, newValue);
485         }
486 
lazySet(T obj, long newValue)487         public final void lazySet(T obj, long newValue) {
488             accessCheck(obj);
489             U.putLongRelease(obj, offset, newValue);
490         }
491 
get(T obj)492         public final long get(T obj) {
493             accessCheck(obj);
494             return U.getLongVolatile(obj, offset);
495         }
496 
getAndSet(T obj, long newValue)497         public final long getAndSet(T obj, long newValue) {
498             accessCheck(obj);
499             return U.getAndSetLong(obj, offset, newValue);
500         }
501 
getAndAdd(T obj, long delta)502         public final long getAndAdd(T obj, long delta) {
503             accessCheck(obj);
504             return U.getAndAddLong(obj, offset, delta);
505         }
506 
getAndIncrement(T obj)507         public final long getAndIncrement(T obj) {
508             return getAndAdd(obj, 1);
509         }
510 
getAndDecrement(T obj)511         public final long getAndDecrement(T obj) {
512             return getAndAdd(obj, -1);
513         }
514 
incrementAndGet(T obj)515         public final long incrementAndGet(T obj) {
516             return getAndAdd(obj, 1) + 1;
517         }
518 
decrementAndGet(T obj)519         public final long decrementAndGet(T obj) {
520             return getAndAdd(obj, -1) - 1;
521         }
522 
addAndGet(T obj, long delta)523         public final long addAndGet(T obj, long delta) {
524             return getAndAdd(obj, delta) + delta;
525         }
526     }
527 
528     private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
529         private static final Unsafe U = Unsafe.getUnsafe();
530         private final long offset;
531         /**
532          * if field is protected, the subclass constructing updater, else
533          * the same as tclass
534          */
535         private final Class<?> cclass;
536         /** class holding the field */
537         private final Class<T> tclass;
538 
539         @SuppressWarnings("removal")
LockedUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller)540         LockedUpdater(final Class<T> tclass, final String fieldName,
541                       final Class<?> caller) {
542             final Field field;
543             final int modifiers;
544             try {
545                 // Android-changed: Skip privilege escalation which is a noop on Android.
546                 /*
547                 field = AccessController.doPrivileged(
548                     new PrivilegedExceptionAction<Field>() {
549                         public Field run() throws NoSuchFieldException {
550                             return tclass.getDeclaredField(fieldName);
551                         }
552                     });
553                 */
554                 field = tclass.getDeclaredField(fieldName);
555                 modifiers = field.getModifiers();
556                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
557                     caller, tclass, null, modifiers);
558                 // Android-removed: Skip checkPackageAccess which is a noop on Android.
559                 /*
560                 ClassLoader cl = tclass.getClassLoader();
561                 ClassLoader ccl = caller.getClassLoader();
562                 if ((ccl != null) && (ccl != cl) &&
563                     ((cl == null) || !isAncestor(cl, ccl))) {
564                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
565                 }
566                 */
567             // Android-removed: Skip privilege escalation which is a noop on Android.
568             /*
569             } catch (PrivilegedActionException pae) {
570                 throw new RuntimeException(pae.getException());
571             */
572             } catch (Exception ex) {
573                 throw new RuntimeException(ex);
574             }
575 
576             if (field.getType() != long.class)
577                 throw new IllegalArgumentException("Must be long type");
578 
579             if (!Modifier.isVolatile(modifiers))
580                 throw new IllegalArgumentException("Must be volatile type");
581 
582             // Access to protected field members is restricted to receivers only
583             // of the accessing class, or one of its subclasses, and the
584             // accessing class must in turn be a subclass (or package sibling)
585             // of the protected member's defining class.
586             // If the updater refers to a protected field of a declaring class
587             // outside the current package, the receiver argument will be
588             // narrowed to the type of the accessing class.
589             this.cclass = (Modifier.isProtected(modifiers) &&
590                            tclass.isAssignableFrom(caller) &&
591                            !isSamePackage(tclass, caller))
592                           ? caller : tclass;
593             this.tclass = tclass;
594             this.offset = U.objectFieldOffset(field);
595         }
596 
597         /**
598          * Checks that target argument is instance of cclass.  On
599          * failure, throws cause.
600          */
accessCheck(T obj)601         private final void accessCheck(T obj) {
602             if (!cclass.isInstance(obj))
603                 throw accessCheckException(obj);
604         }
605 
606         /**
607          * Returns access exception if accessCheck failed due to
608          * protected access, else ClassCastException.
609          */
accessCheckException(T obj)610         private final RuntimeException accessCheckException(T obj) {
611             if (cclass == tclass)
612                 return new ClassCastException();
613             else
614                 return new RuntimeException(
615                     new IllegalAccessException(
616                         "Class " +
617                         cclass.getName() +
618                         " can not access a protected member of class " +
619                         tclass.getName() +
620                         " using an instance of " +
621                         obj.getClass().getName()));
622         }
623 
compareAndSet(T obj, long expect, long update)624         public final boolean compareAndSet(T obj, long expect, long update) {
625             accessCheck(obj);
626             synchronized (this) {
627                 long v = U.getLong(obj, offset);
628                 if (v != expect)
629                     return false;
630                 U.putLong(obj, offset, update);
631                 return true;
632             }
633         }
634 
weakCompareAndSet(T obj, long expect, long update)635         public final boolean weakCompareAndSet(T obj, long expect, long update) {
636             return compareAndSet(obj, expect, update);
637         }
638 
set(T obj, long newValue)639         public final void set(T obj, long newValue) {
640             accessCheck(obj);
641             synchronized (this) {
642                 U.putLong(obj, offset, newValue);
643             }
644         }
645 
lazySet(T obj, long newValue)646         public final void lazySet(T obj, long newValue) {
647             set(obj, newValue);
648         }
649 
get(T obj)650         public final long get(T obj) {
651             accessCheck(obj);
652             synchronized (this) {
653                 return U.getLong(obj, offset);
654             }
655         }
656     }
657 
658     // Android-removed: isAncestor's only usage was removed above.
659     /*
660     /**
661      * Returns true if the second classloader can be found in the first
662      * classloader's delegation chain.
663      * Equivalent to the inaccessible: first.isAncestor(second).
664      *
665     static boolean isAncestor(ClassLoader first, ClassLoader second) {
666         ClassLoader acl = first;
667         do {
668             acl = acl.getParent();
669             if (second == acl) {
670                 return true;
671             }
672         } while (acl != null);
673         return false;
674     }
675     */
676 
677     /**
678      * Returns true if the two classes have the same class loader and
679      * package qualifier
680      */
isSamePackage(Class<?> class1, Class<?> class2)681     static boolean isSamePackage(Class<?> class1, Class<?> class2) {
682         return class1.getClassLoader() == class2.getClassLoader()
683                && class1.getPackageName() == class2.getPackageName();
684     }
685 }
686