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, 1 month ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Log Message:
fork jdk8 maintenance branch for source and jtreg tests

File Contents

# Content
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 }