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.2
Committed: Sat Oct 8 17:34:03 2016 UTC (7 years, 7 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +2 -2 lines
Log Message:
avoid never used local variable assignments

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.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 jsr166 1.2 final Field field;
484     final int modifiers;
485 jsr166 1.1 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     }