ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
Revision: 1.1
Committed: Sat Mar 26 06:22:51 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Log Message:
fork jdk8 maintenance branch for source and jtreg tests

File Contents

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