ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.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

# 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.IntBinaryOperator;
15 import java.util.function.IntUnaryOperator;
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 int} fields of designated classes.
22 * This class is designed for use in atomic data structures in which
23 * several fields of the same node are independently subject to atomic
24 * updates.
25 *
26 * <p>Note that the guarantees of the {@code compareAndSet}
27 * method in this class are weaker than in other atomic classes.
28 * Because this class cannot ensure that all uses of the field
29 * are appropriate for purposes of atomic access, it can
30 * guarantee atomicity only with respect to other invocations of
31 * {@code compareAndSet} and {@code set} on the same updater.
32 *
33 * @since 1.5
34 * @author Doug Lea
35 * @param <T> The type of the object holding the updatable field
36 */
37 public abstract class AtomicIntegerFieldUpdater<T> {
38 /**
39 * Creates and returns an updater for objects with the given field.
40 * The Class argument is needed to check that reflective types and
41 * generic types match.
42 *
43 * @param tclass the class of the objects holding the field
44 * @param fieldName the name of the field to be updated
45 * @param <U> the type of instances of tclass
46 * @return the updater
47 * @throws IllegalArgumentException if the field is not a
48 * volatile integer type
49 * @throws RuntimeException with a nested reflection-based
50 * exception if the class does not hold field or is the wrong type,
51 * or the field is inaccessible to the caller according to Java language
52 * access control
53 */
54 @CallerSensitive
55 public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
56 String fieldName) {
57 return new AtomicIntegerFieldUpdaterImpl<U>
58 (tclass, fieldName, Reflection.getCallerClass());
59 }
60
61 /**
62 * Protected do-nothing constructor for use by subclasses.
63 */
64 protected AtomicIntegerFieldUpdater() {
65 }
66
67 /**
68 * Atomically sets the field of the given object managed by this updater
69 * to the given updated value if the current value {@code ==} the
70 * expected value. This method is guaranteed to be atomic with respect to
71 * other calls to {@code compareAndSet} and {@code set}, but not
72 * necessarily with respect to other changes in the field.
73 *
74 * @param obj An object whose field to conditionally set
75 * @param expect the expected value
76 * @param update the new value
77 * @return {@code true} if successful
78 * @throws ClassCastException if {@code obj} is not an instance
79 * of the class possessing the field established in the constructor
80 */
81 public abstract boolean compareAndSet(T obj, int expect, int update);
82
83 /**
84 * Atomically sets the field of the given object managed by this updater
85 * to the given updated value if the current value {@code ==} the
86 * expected value. This method is guaranteed to be atomic with respect to
87 * other calls to {@code compareAndSet} and {@code set}, but not
88 * necessarily with respect to other changes in the field.
89 *
90 * <p><a href="package-summary.html#weakCompareAndSet">May fail
91 * spuriously and does not provide ordering guarantees</a>, so is
92 * only rarely an appropriate alternative to {@code compareAndSet}.
93 *
94 * @param obj An object whose field to conditionally set
95 * @param expect the expected value
96 * @param update the new value
97 * @return {@code true} if successful
98 * @throws ClassCastException if {@code obj} is not an instance
99 * of the class possessing the field established in the constructor
100 */
101 public abstract boolean weakCompareAndSet(T obj, int expect, int update);
102
103 /**
104 * Sets the field of the given object managed by this updater to the
105 * given updated value. This operation is guaranteed to act as a volatile
106 * store with respect to subsequent invocations of {@code compareAndSet}.
107 *
108 * @param obj An object whose field to set
109 * @param newValue the new value
110 */
111 public abstract void set(T obj, int newValue);
112
113 /**
114 * Eventually sets the field of the given object managed by this
115 * updater to the given updated value.
116 *
117 * @param obj An object whose field to set
118 * @param newValue the new value
119 * @since 1.6
120 */
121 public abstract void lazySet(T obj, int newValue);
122
123 /**
124 * Gets the current value held in the field of the given object managed
125 * by this updater.
126 *
127 * @param obj An object whose field to get
128 * @return the current value
129 */
130 public abstract int get(T obj);
131
132 /**
133 * Atomically sets the field of the given object managed by this updater
134 * to the given value and returns the old value.
135 *
136 * @param obj An object whose field to get and set
137 * @param newValue the new value
138 * @return the previous value
139 */
140 public int getAndSet(T obj, int newValue) {
141 int prev;
142 do {
143 prev = get(obj);
144 } while (!compareAndSet(obj, prev, newValue));
145 return prev;
146 }
147
148 /**
149 * Atomically increments by one the current value of the field of the
150 * given object managed by this updater.
151 *
152 * @param obj An object whose field to get and set
153 * @return the previous value
154 */
155 public int getAndIncrement(T obj) {
156 int prev, next;
157 do {
158 prev = get(obj);
159 next = prev + 1;
160 } while (!compareAndSet(obj, prev, next));
161 return prev;
162 }
163
164 /**
165 * Atomically decrements by one the current value of the field of the
166 * given object managed by this updater.
167 *
168 * @param obj An object whose field to get and set
169 * @return the previous value
170 */
171 public int getAndDecrement(T obj) {
172 int prev, next;
173 do {
174 prev = get(obj);
175 next = prev - 1;
176 } while (!compareAndSet(obj, prev, next));
177 return prev;
178 }
179
180 /**
181 * Atomically adds the given value to the current value of the field of
182 * the given object managed by this updater.
183 *
184 * @param obj An object whose field to get and set
185 * @param delta the value to add
186 * @return the previous value
187 */
188 public int getAndAdd(T obj, int delta) {
189 int prev, next;
190 do {
191 prev = get(obj);
192 next = prev + delta;
193 } while (!compareAndSet(obj, prev, next));
194 return prev;
195 }
196
197 /**
198 * Atomically increments by one the current value of the field of the
199 * given object managed by this updater.
200 *
201 * @param obj An object whose field to get and set
202 * @return the updated value
203 */
204 public int incrementAndGet(T obj) {
205 int prev, next;
206 do {
207 prev = get(obj);
208 next = prev + 1;
209 } while (!compareAndSet(obj, prev, next));
210 return next;
211 }
212
213 /**
214 * Atomically decrements by one the current value of the field of the
215 * given object managed by this updater.
216 *
217 * @param obj An object whose field to get and set
218 * @return the updated value
219 */
220 public int decrementAndGet(T obj) {
221 int prev, next;
222 do {
223 prev = get(obj);
224 next = prev - 1;
225 } while (!compareAndSet(obj, prev, next));
226 return next;
227 }
228
229 /**
230 * Atomically adds the given value to the current value of the field of
231 * the given object managed by this updater.
232 *
233 * @param obj An object whose field to get and set
234 * @param delta the value to add
235 * @return the updated value
236 */
237 public int addAndGet(T obj, int delta) {
238 int prev, next;
239 do {
240 prev = get(obj);
241 next = prev + delta;
242 } while (!compareAndSet(obj, prev, next));
243 return next;
244 }
245
246 /**
247 * Atomically updates the field of the given object managed by this updater
248 * with the results of applying the given function, returning the previous
249 * value. The function should be side-effect-free, since it may be
250 * re-applied when attempted updates fail due to contention among threads.
251 *
252 * @param obj An object whose field to get and set
253 * @param updateFunction a side-effect-free function
254 * @return the previous value
255 * @since 1.8
256 */
257 public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
258 int prev, next;
259 do {
260 prev = get(obj);
261 next = updateFunction.applyAsInt(prev);
262 } while (!compareAndSet(obj, prev, next));
263 return prev;
264 }
265
266 /**
267 * Atomically updates the field of the given object managed by this updater
268 * with the results of applying the given function, returning the updated
269 * value. The function should be side-effect-free, since it may be
270 * re-applied when attempted updates fail due to contention among threads.
271 *
272 * @param obj An object whose field to get and set
273 * @param updateFunction a side-effect-free function
274 * @return the updated value
275 * @since 1.8
276 */
277 public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
278 int prev, next;
279 do {
280 prev = get(obj);
281 next = updateFunction.applyAsInt(prev);
282 } while (!compareAndSet(obj, prev, next));
283 return next;
284 }
285
286 /**
287 * Atomically updates the field of the given object managed by this
288 * updater with the results of applying the given function to the
289 * current and given values, returning the previous value. The
290 * function should be side-effect-free, since it may be re-applied
291 * when attempted updates fail due to contention among threads. The
292 * function is applied with the current value as its first argument,
293 * and the given update as the second argument.
294 *
295 * @param obj An object whose field to get and set
296 * @param x the update value
297 * @param accumulatorFunction a side-effect-free function of two arguments
298 * @return the previous value
299 * @since 1.8
300 */
301 public final int getAndAccumulate(T obj, int x,
302 IntBinaryOperator accumulatorFunction) {
303 int prev, next;
304 do {
305 prev = get(obj);
306 next = accumulatorFunction.applyAsInt(prev, x);
307 } while (!compareAndSet(obj, prev, next));
308 return prev;
309 }
310
311 /**
312 * Atomically updates the field of the given object managed by this
313 * updater with the results of applying the given function to the
314 * current and given values, returning the updated value. The
315 * function should be side-effect-free, since it may be re-applied
316 * when attempted updates fail due to contention among threads. The
317 * function is applied with the current value as its first argument,
318 * and the given update as the second argument.
319 *
320 * @param obj An object whose field to get and set
321 * @param x the update value
322 * @param accumulatorFunction a side-effect-free function of two arguments
323 * @return the updated value
324 * @since 1.8
325 */
326 public final int accumulateAndGet(T obj, int x,
327 IntBinaryOperator accumulatorFunction) {
328 int prev, next;
329 do {
330 prev = get(obj);
331 next = accumulatorFunction.applyAsInt(prev, x);
332 } while (!compareAndSet(obj, prev, next));
333 return next;
334 }
335
336 /**
337 * Standard hotspot implementation using intrinsics.
338 */
339 private static final class AtomicIntegerFieldUpdaterImpl<T>
340 extends AtomicIntegerFieldUpdater<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
351 AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
352 final String fieldName,
353 final Class<?> caller) {
354 final Field field;
355 final int modifiers;
356 try {
357 field = AccessController.doPrivileged(
358 new PrivilegedExceptionAction<Field>() {
359 public Field run() throws NoSuchFieldException {
360 return tclass.getDeclaredField(fieldName);
361 }
362 });
363 modifiers = field.getModifiers();
364 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
365 caller, tclass, null, modifiers);
366 ClassLoader cl = tclass.getClassLoader();
367 ClassLoader ccl = caller.getClassLoader();
368 if ((ccl != null) && (ccl != cl) &&
369 ((cl == null) || !isAncestor(cl, ccl))) {
370 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
371 }
372 } catch (PrivilegedActionException pae) {
373 throw new RuntimeException(pae.getException());
374 } catch (Exception ex) {
375 throw new RuntimeException(ex);
376 }
377
378 if (field.getType() != int.class)
379 throw new IllegalArgumentException("Must be integer type");
380
381 if (!Modifier.isVolatile(modifiers))
382 throw new IllegalArgumentException("Must be volatile type");
383
384 this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
385 this.tclass = tclass;
386 this.offset = U.objectFieldOffset(field);
387 }
388
389 /**
390 * Returns true if the second classloader can be found in the first
391 * classloader's delegation chain.
392 * Equivalent to the inaccessible: first.isAncestor(second).
393 */
394 private static boolean isAncestor(ClassLoader first, ClassLoader second) {
395 ClassLoader acl = first;
396 do {
397 acl = acl.getParent();
398 if (second == acl) {
399 return true;
400 }
401 } while (acl != null);
402 return false;
403 }
404
405 /**
406 * Checks that target argument is instance of cclass. On
407 * failure, throws cause.
408 */
409 private final void accessCheck(T obj) {
410 if (!cclass.isInstance(obj))
411 throwAccessCheckException(obj);
412 }
413
414 /**
415 * Throws access exception if accessCheck failed due to
416 * protected access, else ClassCastException.
417 */
418 private final void throwAccessCheckException(T obj) {
419 if (cclass == tclass)
420 throw new ClassCastException();
421 else
422 throw new RuntimeException(
423 new IllegalAccessException(
424 "Class " +
425 cclass.getName() +
426 " can not access a protected member of class " +
427 tclass.getName() +
428 " using an instance of " +
429 obj.getClass().getName()));
430 }
431
432 public final boolean compareAndSet(T obj, int expect, int update) {
433 accessCheck(obj);
434 return U.compareAndSwapInt(obj, offset, expect, update);
435 }
436
437 public final boolean weakCompareAndSet(T obj, int expect, int update) {
438 accessCheck(obj);
439 return U.compareAndSwapInt(obj, offset, expect, update);
440 }
441
442 public final void set(T obj, int newValue) {
443 accessCheck(obj);
444 U.putIntVolatile(obj, offset, newValue);
445 }
446
447 public final void lazySet(T obj, int newValue) {
448 accessCheck(obj);
449 U.putOrderedInt(obj, offset, newValue);
450 }
451
452 public final int get(T obj) {
453 accessCheck(obj);
454 return U.getIntVolatile(obj, offset);
455 }
456
457 public final int getAndSet(T obj, int newValue) {
458 accessCheck(obj);
459 return U.getAndSetInt(obj, offset, newValue);
460 }
461
462 public final int getAndAdd(T obj, int delta) {
463 accessCheck(obj);
464 return U.getAndAddInt(obj, offset, delta);
465 }
466
467 public final int getAndIncrement(T obj) {
468 return getAndAdd(obj, 1);
469 }
470
471 public final int getAndDecrement(T obj) {
472 return getAndAdd(obj, -1);
473 }
474
475 public final int incrementAndGet(T obj) {
476 return getAndAdd(obj, 1) + 1;
477 }
478
479 public final int decrementAndGet(T obj) {
480 return getAndAdd(obj, -1) - 1;
481 }
482
483 public final int addAndGet(T obj, int delta) {
484 return getAndAdd(obj, delta) + delta;
485 }
486
487 }
488 }