ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
Revision: 1.1
Committed: Sat Mar 26 06:22:51 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
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.LongBinaryOperator;
15 import java.util.function.LongUnaryOperator;
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 long} 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 AtomicLongFieldUpdater<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 long 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> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
56 String fieldName) {
57 Class<?> caller = Reflection.getCallerClass();
58 if (AtomicLong.VM_SUPPORTS_LONG_CAS)
59 return new CASUpdater<U>(tclass, fieldName, caller);
60 else
61 return new LockedUpdater<U>(tclass, fieldName, caller);
62 }
63
64 /**
65 * Protected do-nothing constructor for use by subclasses.
66 */
67 protected AtomicLongFieldUpdater() {
68 }
69
70 /**
71 * Atomically sets the field of the given object managed by this updater
72 * to the given updated value if the current value {@code ==} the
73 * expected value. This method is guaranteed to be atomic with respect to
74 * other calls to {@code compareAndSet} and {@code set}, but not
75 * necessarily with respect to other changes in the field.
76 *
77 * @param obj An object whose field to conditionally set
78 * @param expect the expected value
79 * @param update the new value
80 * @return {@code true} if successful
81 * @throws ClassCastException if {@code obj} is not an instance
82 * of the class possessing the field established in the constructor
83 */
84 public abstract boolean compareAndSet(T obj, long expect, long update);
85
86 /**
87 * Atomically sets the field of the given object managed by this updater
88 * to the given updated value if the current value {@code ==} the
89 * expected value. This method is guaranteed to be atomic with respect to
90 * other calls to {@code compareAndSet} and {@code set}, but not
91 * necessarily with respect to other changes in the field.
92 *
93 * <p><a href="package-summary.html#weakCompareAndSet">May fail
94 * spuriously and does not provide ordering guarantees</a>, so is
95 * only rarely an appropriate alternative to {@code compareAndSet}.
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 * @throws ClassCastException if {@code obj} is not an instance
102 * of the class possessing the field established in the constructor
103 */
104 public abstract boolean weakCompareAndSet(T obj, long expect, long update);
105
106 /**
107 * Sets the field of the given object managed by this updater to the
108 * given updated value. This operation is guaranteed to act as a volatile
109 * store with respect to subsequent invocations of {@code compareAndSet}.
110 *
111 * @param obj An object whose field to set
112 * @param newValue the new value
113 */
114 public abstract void set(T obj, long newValue);
115
116 /**
117 * Eventually sets the field of the given object managed by this
118 * updater to the given updated value.
119 *
120 * @param obj An object whose field to set
121 * @param newValue the new value
122 * @since 1.6
123 */
124 public abstract void lazySet(T obj, long newValue);
125
126 /**
127 * Gets the current value held in the field of the given object managed
128 * by this updater.
129 *
130 * @param obj An object whose field to get
131 * @return the current value
132 */
133 public abstract long get(T obj);
134
135 /**
136 * Atomically sets the field of the given object managed by this updater
137 * to the given value and returns the old value.
138 *
139 * @param obj An object whose field to get and set
140 * @param newValue the new value
141 * @return the previous value
142 */
143 public long getAndSet(T obj, long newValue) {
144 long prev;
145 do {
146 prev = get(obj);
147 } while (!compareAndSet(obj, prev, newValue));
148 return prev;
149 }
150
151 /**
152 * Atomically increments by one the current value of the field of the
153 * given object managed by this updater.
154 *
155 * @param obj An object whose field to get and set
156 * @return the previous value
157 */
158 public long getAndIncrement(T obj) {
159 long prev, next;
160 do {
161 prev = get(obj);
162 next = prev + 1;
163 } while (!compareAndSet(obj, prev, next));
164 return prev;
165 }
166
167 /**
168 * Atomically decrements by one the current value of the field of the
169 * given object managed by this updater.
170 *
171 * @param obj An object whose field to get and set
172 * @return the previous value
173 */
174 public long getAndDecrement(T obj) {
175 long prev, next;
176 do {
177 prev = get(obj);
178 next = prev - 1;
179 } while (!compareAndSet(obj, prev, next));
180 return prev;
181 }
182
183 /**
184 * Atomically adds the given value to the current value of the field of
185 * the given object managed by this updater.
186 *
187 * @param obj An object whose field to get and set
188 * @param delta the value to add
189 * @return the previous value
190 */
191 public long getAndAdd(T obj, long delta) {
192 long prev, next;
193 do {
194 prev = get(obj);
195 next = prev + delta;
196 } while (!compareAndSet(obj, prev, next));
197 return prev;
198 }
199
200 /**
201 * Atomically increments by one the current value of the field of the
202 * given object managed by this updater.
203 *
204 * @param obj An object whose field to get and set
205 * @return the updated value
206 */
207 public long incrementAndGet(T obj) {
208 long prev, next;
209 do {
210 prev = get(obj);
211 next = prev + 1;
212 } while (!compareAndSet(obj, prev, next));
213 return next;
214 }
215
216 /**
217 * Atomically decrements by one the current value of the field of the
218 * given object managed by this updater.
219 *
220 * @param obj An object whose field to get and set
221 * @return the updated value
222 */
223 public long decrementAndGet(T obj) {
224 long prev, next;
225 do {
226 prev = get(obj);
227 next = prev - 1;
228 } while (!compareAndSet(obj, prev, next));
229 return next;
230 }
231
232 /**
233 * Atomically adds the given value to the current value of the field of
234 * the given object managed by this updater.
235 *
236 * @param obj An object whose field to get and set
237 * @param delta the value to add
238 * @return the updated value
239 */
240 public long addAndGet(T obj, long delta) {
241 long prev, next;
242 do {
243 prev = get(obj);
244 next = prev + delta;
245 } while (!compareAndSet(obj, prev, next));
246 return next;
247 }
248
249 /**
250 * Atomically updates the field of the given object managed by this updater
251 * with the results of applying the given function, returning the previous
252 * value. The function should be side-effect-free, since it may be
253 * re-applied when attempted updates fail due to contention among threads.
254 *
255 * @param obj An object whose field to get and set
256 * @param updateFunction a side-effect-free function
257 * @return the previous value
258 * @since 1.8
259 */
260 public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
261 long prev, next;
262 do {
263 prev = get(obj);
264 next = updateFunction.applyAsLong(prev);
265 } while (!compareAndSet(obj, prev, next));
266 return prev;
267 }
268
269 /**
270 * Atomically updates the field of the given object managed by this updater
271 * with the results of applying the given function, returning the updated
272 * value. The function should be side-effect-free, since it may be
273 * re-applied when attempted updates fail due to contention among threads.
274 *
275 * @param obj An object whose field to get and set
276 * @param updateFunction a side-effect-free function
277 * @return the updated value
278 * @since 1.8
279 */
280 public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
281 long prev, next;
282 do {
283 prev = get(obj);
284 next = updateFunction.applyAsLong(prev);
285 } while (!compareAndSet(obj, prev, next));
286 return next;
287 }
288
289 /**
290 * Atomically updates the field of the given object managed by this
291 * updater with the results of applying the given function to the
292 * current and given values, returning the previous value. The
293 * function should be side-effect-free, since it may be re-applied
294 * when attempted updates fail due to contention among threads. The
295 * function is applied with the current value as its first argument,
296 * and the given update as the second argument.
297 *
298 * @param obj An object whose field to get and set
299 * @param x the update value
300 * @param accumulatorFunction a side-effect-free function of two arguments
301 * @return the previous value
302 * @since 1.8
303 */
304 public final long getAndAccumulate(T obj, long x,
305 LongBinaryOperator accumulatorFunction) {
306 long prev, next;
307 do {
308 prev = get(obj);
309 next = accumulatorFunction.applyAsLong(prev, x);
310 } while (!compareAndSet(obj, prev, next));
311 return prev;
312 }
313
314 /**
315 * Atomically updates the field of the given object managed by this
316 * updater with the results of applying the given function to the
317 * current and given values, returning the updated value. The
318 * function should be side-effect-free, since it may be re-applied
319 * when attempted updates fail due to contention among threads. The
320 * function is applied with the current value as its first argument,
321 * and the given update as the second argument.
322 *
323 * @param obj An object whose field to get and set
324 * @param x the update value
325 * @param accumulatorFunction a side-effect-free function of two arguments
326 * @return the updated value
327 * @since 1.8
328 */
329 public final long accumulateAndGet(T obj, long x,
330 LongBinaryOperator accumulatorFunction) {
331 long prev, next;
332 do {
333 prev = get(obj);
334 next = accumulatorFunction.applyAsLong(prev, x);
335 } while (!compareAndSet(obj, prev, next));
336 return next;
337 }
338
339 private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
340 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
341 private final long offset;
342 /**
343 * if field is protected, the subclass constructing updater, else
344 * the same as tclass
345 */
346 private final Class<?> cclass;
347 /** class holding the field */
348 private final Class<T> tclass;
349
350 CASUpdater(final Class<T> tclass, final String fieldName,
351 final Class<?> caller) {
352 final Field field;
353 final int modifiers;
354 try {
355 field = AccessController.doPrivileged(
356 new PrivilegedExceptionAction<Field>() {
357 public Field run() throws NoSuchFieldException {
358 return tclass.getDeclaredField(fieldName);
359 }
360 });
361 modifiers = field.getModifiers();
362 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
363 caller, tclass, null, modifiers);
364 ClassLoader cl = tclass.getClassLoader();
365 ClassLoader ccl = caller.getClassLoader();
366 if ((ccl != null) && (ccl != cl) &&
367 ((cl == null) || !isAncestor(cl, ccl))) {
368 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
369 }
370 } catch (PrivilegedActionException pae) {
371 throw new RuntimeException(pae.getException());
372 } catch (Exception ex) {
373 throw new RuntimeException(ex);
374 }
375
376 if (field.getType() != long.class)
377 throw new IllegalArgumentException("Must be long type");
378
379 if (!Modifier.isVolatile(modifiers))
380 throw new IllegalArgumentException("Must be volatile type");
381
382 this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
383 this.tclass = tclass;
384 this.offset = U.objectFieldOffset(field);
385 }
386
387 /**
388 * Checks that target argument is instance of cclass. On
389 * failure, throws cause.
390 */
391 private final void accessCheck(T obj) {
392 if (!cclass.isInstance(obj))
393 throwAccessCheckException(obj);
394 }
395
396 /**
397 * Throws access exception if accessCheck failed due to
398 * protected access, else ClassCastException.
399 */
400 private final void throwAccessCheckException(T obj) {
401 if (cclass == tclass)
402 throw new ClassCastException();
403 else
404 throw new RuntimeException(
405 new IllegalAccessException(
406 "Class " +
407 cclass.getName() +
408 " can not access a protected member of class " +
409 tclass.getName() +
410 " using an instance of " +
411 obj.getClass().getName()));
412 }
413
414 public final boolean compareAndSet(T obj, long expect, long update) {
415 accessCheck(obj);
416 return U.compareAndSwapLong(obj, offset, expect, update);
417 }
418
419 public final boolean weakCompareAndSet(T obj, long expect, long update) {
420 accessCheck(obj);
421 return U.compareAndSwapLong(obj, offset, expect, update);
422 }
423
424 public final void set(T obj, long newValue) {
425 accessCheck(obj);
426 U.putLongVolatile(obj, offset, newValue);
427 }
428
429 public final void lazySet(T obj, long newValue) {
430 accessCheck(obj);
431 U.putOrderedLong(obj, offset, newValue);
432 }
433
434 public final long get(T obj) {
435 accessCheck(obj);
436 return U.getLongVolatile(obj, offset);
437 }
438
439 public final long getAndSet(T obj, long newValue) {
440 accessCheck(obj);
441 return U.getAndSetLong(obj, offset, newValue);
442 }
443
444 public final long getAndAdd(T obj, long delta) {
445 accessCheck(obj);
446 return U.getAndAddLong(obj, offset, delta);
447 }
448
449 public final long getAndIncrement(T obj) {
450 return getAndAdd(obj, 1);
451 }
452
453 public final long getAndDecrement(T obj) {
454 return getAndAdd(obj, -1);
455 }
456
457 public final long incrementAndGet(T obj) {
458 return getAndAdd(obj, 1) + 1;
459 }
460
461 public final long decrementAndGet(T obj) {
462 return getAndAdd(obj, -1) - 1;
463 }
464
465 public final long addAndGet(T obj, long delta) {
466 return getAndAdd(obj, delta) + delta;
467 }
468 }
469
470 private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
471 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
472 private final long offset;
473 /**
474 * if field is protected, the subclass constructing updater, else
475 * the same as tclass
476 */
477 private final Class<?> cclass;
478 /** class holding the field */
479 private final Class<T> tclass;
480
481 LockedUpdater(final Class<T> tclass, final String fieldName,
482 final Class<?> caller) {
483 Field field = null;
484 int modifiers = 0;
485 try {
486 field = AccessController.doPrivileged(
487 new PrivilegedExceptionAction<Field>() {
488 public Field run() throws NoSuchFieldException {
489 return tclass.getDeclaredField(fieldName);
490 }
491 });
492 modifiers = field.getModifiers();
493 sun.reflect.misc.ReflectUtil.ensureMemberAccess(
494 caller, tclass, null, modifiers);
495 ClassLoader cl = tclass.getClassLoader();
496 ClassLoader ccl = caller.getClassLoader();
497 if ((ccl != null) && (ccl != cl) &&
498 ((cl == null) || !isAncestor(cl, ccl))) {
499 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
500 }
501 } catch (PrivilegedActionException pae) {
502 throw new RuntimeException(pae.getException());
503 } catch (Exception ex) {
504 throw new RuntimeException(ex);
505 }
506
507 if (field.getType() != long.class)
508 throw new IllegalArgumentException("Must be long type");
509
510 if (!Modifier.isVolatile(modifiers))
511 throw new IllegalArgumentException("Must be volatile type");
512
513 this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
514 this.tclass = tclass;
515 this.offset = U.objectFieldOffset(field);
516 }
517
518 /**
519 * Checks that target argument is instance of cclass. On
520 * failure, throws cause.
521 */
522 private final void accessCheck(T obj) {
523 if (!cclass.isInstance(obj))
524 throw accessCheckException(obj);
525 }
526
527 /**
528 * Returns access exception if accessCheck failed due to
529 * protected access, else ClassCastException.
530 */
531 private final RuntimeException accessCheckException(T obj) {
532 if (cclass == tclass)
533 return new ClassCastException();
534 else
535 return new RuntimeException(
536 new IllegalAccessException(
537 "Class " +
538 cclass.getName() +
539 " can not access a protected member of class " +
540 tclass.getName() +
541 " using an instance of " +
542 obj.getClass().getName()));
543 }
544
545 public final boolean compareAndSet(T obj, long expect, long update) {
546 accessCheck(obj);
547 synchronized (this) {
548 long v = U.getLong(obj, offset);
549 if (v != expect)
550 return false;
551 U.putLong(obj, offset, update);
552 return true;
553 }
554 }
555
556 public final boolean weakCompareAndSet(T obj, long expect, long update) {
557 return compareAndSet(obj, expect, update);
558 }
559
560 public final void set(T obj, long newValue) {
561 accessCheck(obj);
562 synchronized (this) {
563 U.putLong(obj, offset, newValue);
564 }
565 }
566
567 public final void lazySet(T obj, long newValue) {
568 set(obj, newValue);
569 }
570
571 public final long get(T obj) {
572 accessCheck(obj);
573 synchronized (this) {
574 return U.getLong(obj, offset);
575 }
576 }
577 }
578
579 /**
580 * Returns true if the second classloader can be found in the first
581 * classloader's delegation chain.
582 * Equivalent to the inaccessible: first.isAncestor(second).
583 */
584 static boolean isAncestor(ClassLoader first, ClassLoader second) {
585 ClassLoader acl = first;
586 do {
587 acl = acl.getParent();
588 if (second == acl) {
589 return true;
590 }
591 } while (acl != null);
592 return false;
593 }
594 }