Home | History | Annotate | Download | only in atomic
      1 /*
      2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      3  *
      4  * This code is free software; you can redistribute it and/or modify it
      5  * under the terms of the GNU General Public License version 2 only, as
      6  * published by the Free Software Foundation.  Oracle designates this
      7  * particular file as subject to the "Classpath" exception as provided
      8  * by Oracle in the LICENSE file that accompanied this code.
      9  *
     10  * This code is distributed in the hope that it will be useful, but WITHOUT
     11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     13  * version 2 for more details (a copy is included in the LICENSE file that
     14  * accompanied this code).
     15  *
     16  * You should have received a copy of the GNU General Public License version
     17  * 2 along with this work; if not, write to the Free Software Foundation,
     18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     19  *
     20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     21  * or visit www.oracle.com if you need additional information or have any
     22  * questions.
     23  */
     24 
     25 /*
     26  * This file is available under and governed by the GNU General Public
     27  * License version 2 only, as published by the Free Software Foundation.
     28  * However, the following notice accompanied the original version of this
     29  * file:
     30  *
     31  * Written by Doug Lea with assistance from members of JCP JSR-166
     32  * Expert Group and released to the public domain, as explained at
     33  * http://creativecommons.org/publicdomain/zero/1.0/
     34  */
     35 
     36 package java.util.concurrent.atomic;
     37 
     38 import dalvik.system.VMStack; // Android-added
     39 import java.lang.reflect.Field;
     40 import java.lang.reflect.Modifier;
     41 import java.security.AccessController;
     42 import java.security.PrivilegedActionException;
     43 import java.security.PrivilegedExceptionAction;
     44 import java.util.function.LongBinaryOperator;
     45 import java.util.function.LongUnaryOperator;
     46 import sun.reflect.CallerSensitive;
     47 import sun.reflect.Reflection;
     48 
     49 /**
     50  * A reflection-based utility that enables atomic updates to
     51  * designated {@code volatile long} fields of designated classes.
     52  * This class is designed for use in atomic data structures in which
     53  * several fields of the same node are independently subject to atomic
     54  * updates.
     55  *
     56  * <p>Note that the guarantees of the {@code compareAndSet}
     57  * method in this class are weaker than in other atomic classes.
     58  * Because this class cannot ensure that all uses of the field
     59  * are appropriate for purposes of atomic access, it can
     60  * guarantee atomicity only with respect to other invocations of
     61  * {@code compareAndSet} and {@code set} on the same updater.
     62  *
     63  * @since 1.5
     64  * @author Doug Lea
     65  * @param <T> The type of the object holding the updatable field
     66  */
     67 public abstract class AtomicLongFieldUpdater<T> {
     68     /**
     69      * Creates and returns an updater for objects with the given field.
     70      * The Class argument is needed to check that reflective types and
     71      * generic types match.
     72      *
     73      * @param tclass the class of the objects holding the field
     74      * @param fieldName the name of the field to be updated
     75      * @param <U> the type of instances of tclass
     76      * @return the updater
     77      * @throws IllegalArgumentException if the field is not a
     78      * volatile long type
     79      * @throws RuntimeException with a nested reflection-based
     80      * exception if the class does not hold field or is the wrong type,
     81      * or the field is inaccessible to the caller according to Java language
     82      * access control
     83      */
     84     @CallerSensitive
     85     public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass,
     86                                                            String fieldName) {
     87       Class<?> caller = VMStack.getStackClass1(); // Android-changed
     88         if (AtomicLong.VM_SUPPORTS_LONG_CAS)
     89             return new CASUpdater<U>(tclass, fieldName, caller);
     90         else
     91             return new LockedUpdater<U>(tclass, fieldName, caller);
     92     }
     93 
     94     /**
     95      * Protected do-nothing constructor for use by subclasses.
     96      */
     97     protected AtomicLongFieldUpdater() {
     98     }
     99 
    100     /**
    101      * Atomically sets the field of the given object managed by this updater
    102      * to the given updated value if the current value {@code ==} the
    103      * expected value. This method is guaranteed to be atomic with respect to
    104      * other calls to {@code compareAndSet} and {@code set}, but not
    105      * necessarily with respect to other changes in the field.
    106      *
    107      * @param obj An object whose field to conditionally set
    108      * @param expect the expected value
    109      * @param update the new value
    110      * @return {@code true} if successful
    111      * @throws ClassCastException if {@code obj} is not an instance
    112      * of the class possessing the field established in the constructor
    113      */
    114     public abstract boolean compareAndSet(T obj, long expect, long update);
    115 
    116     /**
    117      * Atomically sets the field of the given object managed by this updater
    118      * to the given updated value if the current value {@code ==} the
    119      * expected value. This method is guaranteed to be atomic with respect to
    120      * other calls to {@code compareAndSet} and {@code set}, but not
    121      * necessarily with respect to other changes in the field.
    122      *
    123      * <p><a href="package-summary.html#weakCompareAndSet">May fail
    124      * spuriously and does not provide ordering guarantees</a>, so is
    125      * only rarely an appropriate alternative to {@code compareAndSet}.
    126      *
    127      * @param obj An object whose field to conditionally set
    128      * @param expect the expected value
    129      * @param update the new value
    130      * @return {@code true} if successful
    131      * @throws ClassCastException if {@code obj} is not an instance
    132      * of the class possessing the field established in the constructor
    133      */
    134     public abstract boolean weakCompareAndSet(T obj, long expect, long update);
    135 
    136     /**
    137      * Sets the field of the given object managed by this updater to the
    138      * given updated value. This operation is guaranteed to act as a volatile
    139      * store with respect to subsequent invocations of {@code compareAndSet}.
    140      *
    141      * @param obj An object whose field to set
    142      * @param newValue the new value
    143      */
    144     public abstract void set(T obj, long newValue);
    145 
    146     /**
    147      * Eventually sets the field of the given object managed by this
    148      * updater to the given updated value.
    149      *
    150      * @param obj An object whose field to set
    151      * @param newValue the new value
    152      * @since 1.6
    153      */
    154     public abstract void lazySet(T obj, long newValue);
    155 
    156     /**
    157      * Gets the current value held in the field of the given object managed
    158      * by this updater.
    159      *
    160      * @param obj An object whose field to get
    161      * @return the current value
    162      */
    163     public abstract long get(T obj);
    164 
    165     /**
    166      * Atomically sets the field of the given object managed by this updater
    167      * to the given value and returns the old value.
    168      *
    169      * @param obj An object whose field to get and set
    170      * @param newValue the new value
    171      * @return the previous value
    172      */
    173     public long getAndSet(T obj, long newValue) {
    174         long prev;
    175         do {
    176             prev = get(obj);
    177         } while (!compareAndSet(obj, prev, newValue));
    178         return prev;
    179     }
    180 
    181     /**
    182      * Atomically increments by one the current value of the field of the
    183      * given object managed by this updater.
    184      *
    185      * @param obj An object whose field to get and set
    186      * @return the previous value
    187      */
    188     public long getAndIncrement(T obj) {
    189         long prev, next;
    190         do {
    191             prev = get(obj);
    192             next = prev + 1;
    193         } while (!compareAndSet(obj, prev, next));
    194         return prev;
    195     }
    196 
    197     /**
    198      * Atomically decrements 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 previous value
    203      */
    204     public long getAndDecrement(T obj) {
    205         long prev, next;
    206         do {
    207             prev = get(obj);
    208             next = prev - 1;
    209         } while (!compareAndSet(obj, prev, next));
    210         return prev;
    211     }
    212 
    213     /**
    214      * Atomically adds the given value to the current value of the field of
    215      * the given object managed by this updater.
    216      *
    217      * @param obj An object whose field to get and set
    218      * @param delta the value to add
    219      * @return the previous value
    220      */
    221     public long getAndAdd(T obj, long delta) {
    222         long prev, next;
    223         do {
    224             prev = get(obj);
    225             next = prev + delta;
    226         } while (!compareAndSet(obj, prev, next));
    227         return prev;
    228     }
    229 
    230     /**
    231      * Atomically increments by one the current value of the field of the
    232      * given object managed by this updater.
    233      *
    234      * @param obj An object whose field to get and set
    235      * @return the updated value
    236      */
    237     public long incrementAndGet(T obj) {
    238         long prev, next;
    239         do {
    240             prev = get(obj);
    241             next = prev + 1;
    242         } while (!compareAndSet(obj, prev, next));
    243         return next;
    244     }
    245 
    246     /**
    247      * Atomically decrements by one the current value of the field of the
    248      * given object managed by this updater.
    249      *
    250      * @param obj An object whose field to get and set
    251      * @return the updated value
    252      */
    253     public long decrementAndGet(T obj) {
    254         long prev, next;
    255         do {
    256             prev = get(obj);
    257             next = prev - 1;
    258         } while (!compareAndSet(obj, prev, next));
    259         return next;
    260     }
    261 
    262     /**
    263      * Atomically adds the given value to the current value of the field of
    264      * the given object managed by this updater.
    265      *
    266      * @param obj An object whose field to get and set
    267      * @param delta the value to add
    268      * @return the updated value
    269      */
    270     public long addAndGet(T obj, long delta) {
    271         long prev, next;
    272         do {
    273             prev = get(obj);
    274             next = prev + delta;
    275         } while (!compareAndSet(obj, prev, next));
    276         return next;
    277     }
    278 
    279     /**
    280      * Atomically updates the field of the given object managed by this updater
    281      * with the results of applying the given function, returning the previous
    282      * value. The function should be side-effect-free, since it may be
    283      * re-applied when attempted updates fail due to contention among threads.
    284      *
    285      * @param obj An object whose field to get and set
    286      * @param updateFunction a side-effect-free function
    287      * @return the previous value
    288      * @since 1.8
    289      */
    290     public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
    291         long prev, next;
    292         do {
    293             prev = get(obj);
    294             next = updateFunction.applyAsLong(prev);
    295         } while (!compareAndSet(obj, prev, next));
    296         return prev;
    297     }
    298 
    299     /**
    300      * Atomically updates the field of the given object managed by this updater
    301      * with the results of applying the given function, returning the updated
    302      * value. The function should be side-effect-free, since it may be
    303      * re-applied when attempted updates fail due to contention among threads.
    304      *
    305      * @param obj An object whose field to get and set
    306      * @param updateFunction a side-effect-free function
    307      * @return the updated value
    308      * @since 1.8
    309      */
    310     public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
    311         long prev, next;
    312         do {
    313             prev = get(obj);
    314             next = updateFunction.applyAsLong(prev);
    315         } while (!compareAndSet(obj, prev, next));
    316         return next;
    317     }
    318 
    319     /**
    320      * Atomically updates the field of the given object managed by this
    321      * updater with the results of applying the given function to the
    322      * current and given values, returning the previous value. The
    323      * function should be side-effect-free, since it may be re-applied
    324      * when attempted updates fail due to contention among threads.  The
    325      * function is applied with the current value as its first argument,
    326      * and the given update as the second argument.
    327      *
    328      * @param obj An object whose field to get and set
    329      * @param x the update value
    330      * @param accumulatorFunction a side-effect-free function of two arguments
    331      * @return the previous value
    332      * @since 1.8
    333      */
    334     public final long getAndAccumulate(T obj, long x,
    335                                        LongBinaryOperator accumulatorFunction) {
    336         long prev, next;
    337         do {
    338             prev = get(obj);
    339             next = accumulatorFunction.applyAsLong(prev, x);
    340         } while (!compareAndSet(obj, prev, next));
    341         return prev;
    342     }
    343 
    344     /**
    345      * Atomically updates the field of the given object managed by this
    346      * updater with the results of applying the given function to the
    347      * current and given values, returning the updated value. The
    348      * function should be side-effect-free, since it may be re-applied
    349      * when attempted updates fail due to contention among threads.  The
    350      * function is applied with the current value as its first argument,
    351      * and the given update as the second argument.
    352      *
    353      * @param obj An object whose field to get and set
    354      * @param x the update value
    355      * @param accumulatorFunction a side-effect-free function of two arguments
    356      * @return the updated value
    357      * @since 1.8
    358      */
    359     public final long accumulateAndGet(T obj, long x,
    360                                        LongBinaryOperator accumulatorFunction) {
    361         long prev, next;
    362         do {
    363             prev = get(obj);
    364             next = accumulatorFunction.applyAsLong(prev, x);
    365         } while (!compareAndSet(obj, prev, next));
    366         return next;
    367     }
    368 
    369     private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
    370         private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
    371         private final long offset;
    372         /**
    373          * if field is protected, the subclass constructing updater, else
    374          * the same as tclass
    375          */
    376         private final Class<?> cclass;
    377         /** class holding the field */
    378         private final Class<T> tclass;
    379 
    380         CASUpdater(final Class<T> tclass, final String fieldName,
    381                    final Class<?> caller) {
    382             final Field field;
    383             final int modifiers;
    384             try {
    385                 field = tclass.getDeclaredField(fieldName); // Android-changed
    386                 modifiers = field.getModifiers();
    387                 // BEGIN Android-removed
    388                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
    389                 //     caller, tclass, null, modifiers);
    390                 // ClassLoader cl = tclass.getClassLoader();
    391                 // ClassLoader ccl = caller.getClassLoader();
    392                 // if ((ccl != null) && (ccl != cl) &&
    393                 //     ((cl == null) || !isAncestor(cl, ccl))) {
    394                 //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
    395                 // }
    396                 // END Android-removed
    397             // BEGIN Android-removed
    398             // } catch (PrivilegedActionException pae) {
    399             //     throw new RuntimeException(pae.getException());
    400             // END Android-removed
    401             } catch (Exception ex) {
    402                 throw new RuntimeException(ex);
    403             }
    404 
    405             if (field.getType() != long.class)
    406                 throw new IllegalArgumentException("Must be long type");
    407 
    408             if (!Modifier.isVolatile(modifiers))
    409                 throw new IllegalArgumentException("Must be volatile type");
    410 
    411             this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
    412             this.tclass = tclass;
    413             this.offset = U.objectFieldOffset(field);
    414         }
    415 
    416         /**
    417          * Checks that target argument is instance of cclass.  On
    418          * failure, throws cause.
    419          */
    420         private final void accessCheck(T obj) {
    421             if (!cclass.isInstance(obj))
    422                 throwAccessCheckException(obj);
    423         }
    424 
    425         /**
    426          * Throws access exception if accessCheck failed due to
    427          * protected access, else ClassCastException.
    428          */
    429         private final void throwAccessCheckException(T obj) {
    430             if (cclass == tclass)
    431                 throw new ClassCastException();
    432             else
    433                 throw new RuntimeException(
    434                     new IllegalAccessException(
    435                         "Class " +
    436                         cclass.getName() +
    437                         " can not access a protected member of class " +
    438                         tclass.getName() +
    439                         " using an instance of " +
    440                         obj.getClass().getName()));
    441         }
    442 
    443         public final boolean compareAndSet(T obj, long expect, long update) {
    444             accessCheck(obj);
    445             return U.compareAndSwapLong(obj, offset, expect, update);
    446         }
    447 
    448         public final boolean weakCompareAndSet(T obj, long expect, long update) {
    449             accessCheck(obj);
    450             return U.compareAndSwapLong(obj, offset, expect, update);
    451         }
    452 
    453         public final void set(T obj, long newValue) {
    454             accessCheck(obj);
    455             U.putLongVolatile(obj, offset, newValue);
    456         }
    457 
    458         public final void lazySet(T obj, long newValue) {
    459             accessCheck(obj);
    460             U.putOrderedLong(obj, offset, newValue);
    461         }
    462 
    463         public final long get(T obj) {
    464             accessCheck(obj);
    465             return U.getLongVolatile(obj, offset);
    466         }
    467 
    468         public final long getAndSet(T obj, long newValue) {
    469             accessCheck(obj);
    470             return U.getAndSetLong(obj, offset, newValue);
    471         }
    472 
    473         public final long getAndAdd(T obj, long delta) {
    474             accessCheck(obj);
    475             return U.getAndAddLong(obj, offset, delta);
    476         }
    477 
    478         public final long getAndIncrement(T obj) {
    479             return getAndAdd(obj, 1);
    480         }
    481 
    482         public final long getAndDecrement(T obj) {
    483             return getAndAdd(obj, -1);
    484         }
    485 
    486         public final long incrementAndGet(T obj) {
    487             return getAndAdd(obj, 1) + 1;
    488         }
    489 
    490         public final long decrementAndGet(T obj) {
    491             return getAndAdd(obj, -1) - 1;
    492         }
    493 
    494         public final long addAndGet(T obj, long delta) {
    495             return getAndAdd(obj, delta) + delta;
    496         }
    497     }
    498 
    499     private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
    500         private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
    501         private final long offset;
    502         /**
    503          * if field is protected, the subclass constructing updater, else
    504          * the same as tclass
    505          */
    506         private final Class<?> cclass;
    507         /** class holding the field */
    508         private final Class<T> tclass;
    509 
    510         LockedUpdater(final Class<T> tclass, final String fieldName,
    511                       final Class<?> caller) {
    512             Field field = null;
    513             int modifiers = 0;
    514             try {
    515                 field = tclass.getDeclaredField(fieldName); // Android-changed
    516                 modifiers = field.getModifiers();
    517                 // BEGIN Android-removed
    518                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
    519                 //     caller, tclass, null, modifiers);
    520                 // ClassLoader cl = tclass.getClassLoader();
    521                 // ClassLoader ccl = caller.getClassLoader();
    522                 // if ((ccl != null) && (ccl != cl) &&
    523                 //     ((cl == null) || !isAncestor(cl, ccl))) {
    524                 //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
    525                 // }
    526                 // END Android-removed
    527             // BEGIN Android-removed
    528             // } catch (PrivilegedActionException pae) {
    529             //     throw new RuntimeException(pae.getException());
    530             // END Android-removed
    531             } catch (Exception ex) {
    532                 throw new RuntimeException(ex);
    533             }
    534 
    535             if (field.getType() != long.class)
    536                 throw new IllegalArgumentException("Must be long type");
    537 
    538             if (!Modifier.isVolatile(modifiers))
    539                 throw new IllegalArgumentException("Must be volatile type");
    540 
    541             this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
    542             this.tclass = tclass;
    543             this.offset = U.objectFieldOffset(field);
    544         }
    545 
    546         /**
    547          * Checks that target argument is instance of cclass.  On
    548          * failure, throws cause.
    549          */
    550         private final void accessCheck(T obj) {
    551             if (!cclass.isInstance(obj))
    552                 throw accessCheckException(obj);
    553         }
    554 
    555         /**
    556          * Returns access exception if accessCheck failed due to
    557          * protected access, else ClassCastException.
    558          */
    559         private final RuntimeException accessCheckException(T obj) {
    560             if (cclass == tclass)
    561                 return new ClassCastException();
    562             else
    563                 return new RuntimeException(
    564                     new IllegalAccessException(
    565                         "Class " +
    566                         cclass.getName() +
    567                         " can not access a protected member of class " +
    568                         tclass.getName() +
    569                         " using an instance of " +
    570                         obj.getClass().getName()));
    571         }
    572 
    573         public final boolean compareAndSet(T obj, long expect, long update) {
    574             accessCheck(obj);
    575             synchronized (this) {
    576                 long v = U.getLong(obj, offset);
    577                 if (v != expect)
    578                     return false;
    579                 U.putLong(obj, offset, update);
    580                 return true;
    581             }
    582         }
    583 
    584         public final boolean weakCompareAndSet(T obj, long expect, long update) {
    585             return compareAndSet(obj, expect, update);
    586         }
    587 
    588         public final void set(T obj, long newValue) {
    589             accessCheck(obj);
    590             synchronized (this) {
    591                 U.putLong(obj, offset, newValue);
    592             }
    593         }
    594 
    595         public final void lazySet(T obj, long newValue) {
    596             set(obj, newValue);
    597         }
    598 
    599         public final long get(T obj) {
    600             accessCheck(obj);
    601             synchronized (this) {
    602                 return U.getLong(obj, offset);
    603             }
    604         }
    605     }
    606 
    607     // BEGIN Android-removed
    608     // /**
    609     //  * Returns true if the second classloader can be found in the first
    610     //  * classloader's delegation chain.
    611     //  * Equivalent to the inaccessible: first.isAncestor(second).
    612     //  */
    613     // static boolean isAncestor(ClassLoader first, ClassLoader second) {
    614     //     ClassLoader acl = first;
    615     //     do {
    616     //         acl = acl.getParent();
    617     //         if (second == acl) {
    618     //             return true;
    619     //         }
    620     //     } while (acl != null);
    621     //     return false;
    622     // }
    623     // END Android-removed
    624 }
    625