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.Objects;
44 import java.util.function.LongBinaryOperator;
45 import java.util.function.LongUnaryOperator;
46 import jdk.internal.misc.Unsafe;
47 import jdk.internal.reflect.CallerSensitive;
48 import jdk.internal.reflect.Reflection;
49 import 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  */
73 public 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
newUpdater(Class<U> tclass, String fieldName)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      */
AtomicLongFieldUpdater()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      */
compareAndSet(T obj, long expect, long update)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      */
weakCompareAndSet(T obj, long expect, long update)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      */
set(T obj, long newValue)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      */
lazySet(T obj, long newValue)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      */
get(T obj)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      */
getAndSet(T obj, long newValue)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      */
getAndIncrement(T obj)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      */
getAndDecrement(T obj)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      */
getAndAdd(T obj, long delta)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      */
incrementAndGet(T obj)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      */
decrementAndGet(T obj)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      */
addAndGet(T obj, long delta)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      */
getAndUpdate(T obj, LongUnaryOperator updateFunction)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      */
updateAndGet(T obj, LongUnaryOperator updateFunction)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      */
getAndAccumulate(T obj, long x, LongBinaryOperator accumulatorFunction)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      */
accumulateAndGet(T obj, long x, LongBinaryOperator accumulatorFunction)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 
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 
LockedUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller)539         LockedUpdater(final Class<T> tclass, final String fieldName,
540                       final Class<?> caller) {
541             final Field field;
542             final int modifiers;
543             try {
544                 // Android-changed: Skip privilege escalation which is a noop on Android.
545                 /*
546                 field = AccessController.doPrivileged(
547                     new PrivilegedExceptionAction<Field>() {
548                         public Field run() throws NoSuchFieldException {
549                             return tclass.getDeclaredField(fieldName);
550                         }
551                     });
552                 */
553                 field = tclass.getDeclaredField(fieldName);
554                 modifiers = field.getModifiers();
555                 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
556                     caller, tclass, null, modifiers);
557                 // Android-removed: Skip checkPackageAccess which is a noop on Android.
558                 /*
559                 ClassLoader cl = tclass.getClassLoader();
560                 ClassLoader ccl = caller.getClassLoader();
561                 if ((ccl != null) && (ccl != cl) &&
562                     ((cl == null) || !isAncestor(cl, ccl))) {
563                     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
564                 }
565                 */
566             // Android-removed: Skip privilege escalation which is a noop on Android.
567             /*
568             } catch (PrivilegedActionException pae) {
569                 throw new RuntimeException(pae.getException());
570             */
571             } catch (Exception ex) {
572                 throw new RuntimeException(ex);
573             }
574 
575             if (field.getType() != long.class)
576                 throw new IllegalArgumentException("Must be long type");
577 
578             if (!Modifier.isVolatile(modifiers))
579                 throw new IllegalArgumentException("Must be volatile type");
580 
581             // Access to protected field members is restricted to receivers only
582             // of the accessing class, or one of its subclasses, and the
583             // accessing class must in turn be a subclass (or package sibling)
584             // of the protected member's defining class.
585             // If the updater refers to a protected field of a declaring class
586             // outside the current package, the receiver argument will be
587             // narrowed to the type of the accessing class.
588             this.cclass = (Modifier.isProtected(modifiers) &&
589                            tclass.isAssignableFrom(caller) &&
590                            !isSamePackage(tclass, caller))
591                           ? caller : tclass;
592             this.tclass = tclass;
593             this.offset = U.objectFieldOffset(field);
594         }
595 
596         /**
597          * Checks that target argument is instance of cclass.  On
598          * failure, throws cause.
599          */
accessCheck(T obj)600         private final void accessCheck(T obj) {
601             if (!cclass.isInstance(obj))
602                 throw accessCheckException(obj);
603         }
604 
605         /**
606          * Returns access exception if accessCheck failed due to
607          * protected access, else ClassCastException.
608          */
accessCheckException(T obj)609         private final RuntimeException accessCheckException(T obj) {
610             if (cclass == tclass)
611                 return new ClassCastException();
612             else
613                 return new RuntimeException(
614                     new IllegalAccessException(
615                         "Class " +
616                         cclass.getName() +
617                         " can not access a protected member of class " +
618                         tclass.getName() +
619                         " using an instance of " +
620                         obj.getClass().getName()));
621         }
622 
compareAndSet(T obj, long expect, long update)623         public final boolean compareAndSet(T obj, long expect, long update) {
624             accessCheck(obj);
625             synchronized (this) {
626                 long v = U.getLong(obj, offset);
627                 if (v != expect)
628                     return false;
629                 U.putLong(obj, offset, update);
630                 return true;
631             }
632         }
633 
weakCompareAndSet(T obj, long expect, long update)634         public final boolean weakCompareAndSet(T obj, long expect, long update) {
635             return compareAndSet(obj, expect, update);
636         }
637 
set(T obj, long newValue)638         public final void set(T obj, long newValue) {
639             accessCheck(obj);
640             synchronized (this) {
641                 U.putLong(obj, offset, newValue);
642             }
643         }
644 
lazySet(T obj, long newValue)645         public final void lazySet(T obj, long newValue) {
646             set(obj, newValue);
647         }
648 
get(T obj)649         public final long get(T obj) {
650             accessCheck(obj);
651             synchronized (this) {
652                 return U.getLong(obj, offset);
653             }
654         }
655     }
656 
657     // Android-removed: isAncestor's only usage was removed above.
658     /*
659     /**
660      * Returns true if the second classloader can be found in the first
661      * classloader's delegation chain.
662      * Equivalent to the inaccessible: first.isAncestor(second).
663      *
664     static boolean isAncestor(ClassLoader first, ClassLoader second) {
665         ClassLoader acl = first;
666         do {
667             acl = acl.getParent();
668             if (second == acl) {
669                 return true;
670             }
671         } while (acl != null);
672         return false;
673     }
674     */
675 
676     /**
677      * Returns true if the two classes have the same class loader and
678      * package qualifier
679      */
isSamePackage(Class<?> class1, Class<?> class2)680     static boolean isSamePackage(Class<?> class1, Class<?> class2) {
681         return class1.getClassLoader() == class2.getClassLoader()
682             && Objects.equals(class1.getPackageName(), class2.getPackageName());
683     }
684 }
685