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