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