• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.BinaryOperator;
16 import java.util.function.UnaryOperator;
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} reference fields of designated
23  * classes.  This class is designed for use in atomic data structures
24  * in which several reference fields of the same node are
25  * independently subject to atomic updates. For example, a tree node
26  * might be declared as
27  *
28  * <pre> {@code
29  * class Node {
30  *   private volatile Node left, right;
31  *
32  *   private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
33  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
34  *   private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
35  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
36  *
37  *   Node getLeft() { return left; }
38  *   boolean compareAndSetLeft(Node expect, Node update) {
39  *     return leftUpdater.compareAndSet(this, expect, update);
40  *   }
41  *   // ... and so on
42  * }}</pre>
43  *
44  * <p>Note that the guarantees of the {@code compareAndSet}
45  * method in this class are weaker than in other atomic classes.
46  * Because this class cannot ensure that all uses of the field
47  * are appropriate for purposes of atomic access, it can
48  * guarantee atomicity only with respect to other invocations of
49  * {@code compareAndSet} and {@code set} on the same updater.
50  *
51  * @since 1.5
52  * @author Doug Lea
53  * @param <T> The type of the object holding the updatable field
54  * @param <V> The type of the field
55  */
56 public abstract class AtomicReferenceFieldUpdater<T,V> {
57 
58     /**
59      * Creates and returns an updater for objects with the given field.
60      * The Class arguments are needed to check that reflective types and
61      * generic types match.
62      *
63      * @param tclass the class of the objects holding the field
64      * @param vclass the class of the field
65      * @param fieldName the name of the field to be updated
66      * @param <U> the type of instances of tclass
67      * @param <W> the type of instances of vclass
68      * @return the updater
69      * @throws ClassCastException if the field is of the wrong type
70      * @throws IllegalArgumentException if the field is not volatile
71      * @throws RuntimeException with a nested reflection-based
72      * exception if the class does not hold field or is the wrong type,
73      * or the field is inaccessible to the caller according to Java language
74      * access control
75      */
76     @CallerSensitive
newUpdater(Class<U> tclass, Class<W> vclass, String fieldName)77     public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
78                                                                     Class<W> vclass,
79                                                                     String fieldName) {
80         return new AtomicReferenceFieldUpdaterImpl<U,W>
81             (tclass, vclass, fieldName, VMStack.getStackClass1()); // android-changed
82     }
83 
84     /**
85      * Protected do-nothing constructor for use by subclasses.
86      */
AtomicReferenceFieldUpdater()87     protected AtomicReferenceFieldUpdater() {
88     }
89 
90     /**
91      * Atomically sets the field of the given object managed by this updater
92      * to the given updated value if the current value {@code ==} the
93      * expected value. This method is guaranteed to be atomic with respect to
94      * other calls to {@code compareAndSet} and {@code set}, but not
95      * necessarily with respect to other changes in the field.
96      *
97      * @param obj An object whose field to conditionally set
98      * @param expect the expected value
99      * @param update the new value
100      * @return {@code true} if successful
101      */
compareAndSet(T obj, V expect, V update)102     public abstract boolean compareAndSet(T obj, V expect, V update);
103 
104     /**
105      * Atomically sets the field of the given object managed by this updater
106      * to the given updated value if the current value {@code ==} the
107      * expected value. This method is guaranteed to be atomic with respect to
108      * other calls to {@code compareAndSet} and {@code set}, but not
109      * necessarily with respect to other changes in the field.
110      *
111      * <p><a href="package-summary.html#weakCompareAndSet">May fail
112      * spuriously and does not provide ordering guarantees</a>, so is
113      * only rarely an appropriate alternative to {@code compareAndSet}.
114      *
115      * @param obj An object whose field to conditionally set
116      * @param expect the expected value
117      * @param update the new value
118      * @return {@code true} if successful
119      */
weakCompareAndSet(T obj, V expect, V update)120     public abstract boolean weakCompareAndSet(T obj, V expect, V update);
121 
122     /**
123      * Sets the field of the given object managed by this updater to the
124      * given updated value. This operation is guaranteed to act as a volatile
125      * store with respect to subsequent invocations of {@code compareAndSet}.
126      *
127      * @param obj An object whose field to set
128      * @param newValue the new value
129      */
set(T obj, V newValue)130     public abstract void set(T obj, V newValue);
131 
132     /**
133      * Eventually sets the field of the given object managed by this
134      * updater to the given updated value.
135      *
136      * @param obj An object whose field to set
137      * @param newValue the new value
138      * @since 1.6
139      */
lazySet(T obj, V newValue)140     public abstract void lazySet(T obj, V newValue);
141 
142     /**
143      * Gets the current value held in the field of the given object managed
144      * by this updater.
145      *
146      * @param obj An object whose field to get
147      * @return the current value
148      */
get(T obj)149     public abstract V get(T obj);
150 
151     /**
152      * Atomically sets the field of the given object managed by this updater
153      * to the given value and returns the old value.
154      *
155      * @param obj An object whose field to get and set
156      * @param newValue the new value
157      * @return the previous value
158      */
getAndSet(T obj, V newValue)159     public V getAndSet(T obj, V newValue) {
160         V prev;
161         do {
162             prev = get(obj);
163         } while (!compareAndSet(obj, prev, newValue));
164         return prev;
165     }
166 
167     /**
168      * Atomically updates the field of the given object managed by this updater
169      * with the results of applying the given function, returning the previous
170      * value. The function should be side-effect-free, since it may be
171      * re-applied when attempted updates fail due to contention among threads.
172      *
173      * @param obj An object whose field to get and set
174      * @param updateFunction a side-effect-free function
175      * @return the previous value
176      * @since 1.8
177      */
getAndUpdate(T obj, UnaryOperator<V> updateFunction)178     public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) {
179         V prev, next;
180         do {
181             prev = get(obj);
182             next = updateFunction.apply(prev);
183         } while (!compareAndSet(obj, prev, next));
184         return prev;
185     }
186 
187     /**
188      * Atomically updates the field of the given object managed by this updater
189      * with the results of applying the given function, returning the updated
190      * value. The function should be side-effect-free, since it may be
191      * re-applied when attempted updates fail due to contention among threads.
192      *
193      * @param obj An object whose field to get and set
194      * @param updateFunction a side-effect-free function
195      * @return the updated value
196      * @since 1.8
197      */
updateAndGet(T obj, UnaryOperator<V> updateFunction)198     public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) {
199         V prev, next;
200         do {
201             prev = get(obj);
202             next = updateFunction.apply(prev);
203         } while (!compareAndSet(obj, prev, next));
204         return next;
205     }
206 
207     /**
208      * Atomically updates the field of the given object managed by this
209      * updater with the results of applying the given function to the
210      * current and given values, returning the previous value. The
211      * function should be side-effect-free, since it may be re-applied
212      * when attempted updates fail due to contention among threads.  The
213      * function is applied with the current value as its first argument,
214      * and the given update as the second argument.
215      *
216      * @param obj An object whose field to get and set
217      * @param x the update value
218      * @param accumulatorFunction a side-effect-free function of two arguments
219      * @return the previous value
220      * @since 1.8
221      */
getAndAccumulate(T obj, V x, BinaryOperator<V> accumulatorFunction)222     public final V getAndAccumulate(T obj, V x,
223                                     BinaryOperator<V> accumulatorFunction) {
224         V prev, next;
225         do {
226             prev = get(obj);
227             next = accumulatorFunction.apply(prev, x);
228         } while (!compareAndSet(obj, prev, next));
229         return prev;
230     }
231 
232     /**
233      * Atomically updates the field of the given object managed by this
234      * updater with the results of applying the given function to the
235      * current and given values, returning the updated value. The
236      * function should be side-effect-free, since it may be re-applied
237      * when attempted updates fail due to contention among threads.  The
238      * function is applied with the current value as its first argument,
239      * and the given update as the second argument.
240      *
241      * @param obj An object whose field to get and set
242      * @param x the update value
243      * @param accumulatorFunction a side-effect-free function of two arguments
244      * @return the updated value
245      * @since 1.8
246      */
accumulateAndGet(T obj, V x, BinaryOperator<V> accumulatorFunction)247     public final V accumulateAndGet(T obj, V x,
248                                     BinaryOperator<V> accumulatorFunction) {
249         V prev, next;
250         do {
251             prev = get(obj);
252             next = accumulatorFunction.apply(prev, x);
253         } while (!compareAndSet(obj, prev, next));
254         return next;
255     }
256 
257     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
258         extends AtomicReferenceFieldUpdater<T,V> {
259         private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
260         private final long offset;
261         /**
262          * if field is protected, the subclass constructing updater, else
263          * the same as tclass
264          */
265         private final Class<?> cclass;
266         /** class holding the field */
267         private final Class<T> tclass;
268         /** field value type */
269         private final Class<V> vclass;
270 
271         /*
272          * Internal type checks within all update methods contain
273          * internal inlined optimizations checking for the common
274          * cases where the class is final (in which case a simple
275          * getClass comparison suffices) or is of type Object (in
276          * which case no check is needed because all objects are
277          * instances of Object). The Object case is handled simply by
278          * setting vclass to null in constructor.  The targetCheck and
279          * updateCheck methods are invoked when these faster
280          * screenings fail.
281          */
282 
AtomicReferenceFieldUpdaterImpl(final Class<T> tclass, final Class<V> vclass, final String fieldName, final Class<?> caller)283         AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
284                                         final Class<V> vclass,
285                                         final String fieldName,
286                                         final Class<?> caller) {
287             final Field field;
288             final Class<?> fieldClass;
289             final int modifiers;
290             try {
291                 field = tclass.getDeclaredField(fieldName); // android-changed
292                 modifiers = field.getModifiers();
293                 // BEGIN android-removed
294                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
295                 //     caller, tclass, null, modifiers);
296                 // ClassLoader cl = tclass.getClassLoader();
297                 // ClassLoader ccl = caller.getClassLoader();
298                 // if ((ccl != null) && (ccl != cl) &&
299                 //     ((cl == null) || !isAncestor(cl, ccl))) {
300                 //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
301                 // }
302                 // END android-removed
303                 fieldClass = field.getType();
304             // BEGIN android-removed
305             // } catch (PrivilegedActionException pae) {
306             //     throw new RuntimeException(pae.getException());
307             // END android-removed
308             } catch (Exception ex) {
309                 throw new RuntimeException(ex);
310             }
311 
312             if (vclass != fieldClass)
313                 throw new ClassCastException();
314             if (vclass.isPrimitive())
315                 throw new IllegalArgumentException("Must be reference type");
316 
317             if (!Modifier.isVolatile(modifiers))
318                 throw new IllegalArgumentException("Must be volatile type");
319 
320             this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
321             this.tclass = tclass;
322             this.vclass = vclass;
323             this.offset = U.objectFieldOffset(field);
324         }
325 
326         // BEGIN android-removed
327         // /**
328         //  * Returns true if the second classloader can be found in the first
329         //  * classloader's delegation chain.
330         //  * Equivalent to the inaccessible: first.isAncestor(second).
331         //  */
332         // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
333         //     ClassLoader acl = first;
334         //     do {
335         //         acl = acl.getParent();
336         //         if (second == acl) {
337         //             return true;
338         //         }
339         //     } while (acl != null);
340         //     return false;
341         // }
342         // END android-removed
343 
344         /**
345          * Checks that target argument is instance of cclass.  On
346          * failure, throws cause.
347          */
accessCheck(T obj)348         private final void accessCheck(T obj) {
349             if (!cclass.isInstance(obj))
350                 throwAccessCheckException(obj);
351         }
352 
353         /**
354          * Throws access exception if accessCheck failed due to
355          * protected access, else ClassCastException.
356          */
throwAccessCheckException(T obj)357         private final void throwAccessCheckException(T obj) {
358             if (cclass == tclass)
359                 throw new ClassCastException();
360             else
361                 throw new RuntimeException(
362                     new IllegalAccessException(
363                         "Class " +
364                         cclass.getName() +
365                         " can not access a protected member of class " +
366                         tclass.getName() +
367                         " using an instance of " +
368                         obj.getClass().getName()));
369         }
370 
valueCheck(V v)371         private final void valueCheck(V v) {
372             if (v != null && !(vclass.isInstance(v)))
373                 throwCCE();
374         }
375 
throwCCE()376         static void throwCCE() {
377             throw new ClassCastException();
378         }
379 
compareAndSet(T obj, V expect, V update)380         public final boolean compareAndSet(T obj, V expect, V update) {
381             accessCheck(obj);
382             valueCheck(update);
383             return U.compareAndSwapObject(obj, offset, expect, update);
384         }
385 
weakCompareAndSet(T obj, V expect, V update)386         public final boolean weakCompareAndSet(T obj, V expect, V update) {
387             // same implementation as strong form for now
388             accessCheck(obj);
389             valueCheck(update);
390             return U.compareAndSwapObject(obj, offset, expect, update);
391         }
392 
set(T obj, V newValue)393         public final void set(T obj, V newValue) {
394             accessCheck(obj);
395             valueCheck(newValue);
396             U.putObjectVolatile(obj, offset, newValue);
397         }
398 
lazySet(T obj, V newValue)399         public final void lazySet(T obj, V newValue) {
400             accessCheck(obj);
401             valueCheck(newValue);
402             U.putOrderedObject(obj, offset, newValue);
403         }
404 
405         @SuppressWarnings("unchecked")
get(T obj)406         public final V get(T obj) {
407             accessCheck(obj);
408             return (V)U.getObjectVolatile(obj, offset);
409         }
410 
411         @SuppressWarnings("unchecked")
getAndSet(T obj, V newValue)412         public final V getAndSet(T obj, V newValue) {
413             accessCheck(obj);
414             valueCheck(newValue);
415             return (V)U.getAndSetObject(obj, offset, newValue);
416         }
417     }
418 }
419