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.BinaryOperator;
     45 import java.util.function.UnaryOperator;
     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} reference fields of designated
     52  * classes.  This class is designed for use in atomic data structures
     53  * in which several reference fields of the same node are
     54  * independently subject to atomic updates. For example, a tree node
     55  * might be declared as
     56  *
     57  * <pre> {@code
     58  * class Node {
     59  *   private volatile Node left, right;
     60  *
     61  *   private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
     62  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
     63  *   private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
     64  *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
     65  *
     66  *   Node getLeft() { return left; }
     67  *   boolean compareAndSetLeft(Node expect, Node update) {
     68  *     return leftUpdater.compareAndSet(this, expect, update);
     69  *   }
     70  *   // ... and so on
     71  * }}</pre>
     72  *
     73  * <p>Note that the guarantees of the {@code compareAndSet}
     74  * method in this class are weaker than in other atomic classes.
     75  * Because this class cannot ensure that all uses of the field
     76  * are appropriate for purposes of atomic access, it can
     77  * guarantee atomicity only with respect to other invocations of
     78  * {@code compareAndSet} and {@code set} on the same updater.
     79  *
     80  * @since 1.5
     81  * @author Doug Lea
     82  * @param <T> The type of the object holding the updatable field
     83  * @param <V> The type of the field
     84  */
     85 public abstract class AtomicReferenceFieldUpdater<T,V> {
     86 
     87     /**
     88      * Creates and returns an updater for objects with the given field.
     89      * The Class arguments are needed to check that reflective types and
     90      * generic types match.
     91      *
     92      * @param tclass the class of the objects holding the field
     93      * @param vclass the class of the field
     94      * @param fieldName the name of the field to be updated
     95      * @param <U> the type of instances of tclass
     96      * @param <W> the type of instances of vclass
     97      * @return the updater
     98      * @throws ClassCastException if the field is of the wrong type
     99      * @throws IllegalArgumentException if the field is not volatile
    100      * @throws RuntimeException with a nested reflection-based
    101      * exception if the class does not hold field or is the wrong type,
    102      * or the field is inaccessible to the caller according to Java language
    103      * access control
    104      */
    105     @CallerSensitive
    106     public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass,
    107                                                                     Class<W> vclass,
    108                                                                     String fieldName) {
    109         return new AtomicReferenceFieldUpdaterImpl<U,W>
    110             (tclass, vclass, fieldName, VMStack.getStackClass1()); // Android-changed
    111     }
    112 
    113     /**
    114      * Protected do-nothing constructor for use by subclasses.
    115      */
    116     protected AtomicReferenceFieldUpdater() {
    117     }
    118 
    119     /**
    120      * Atomically sets the field of the given object managed by this updater
    121      * to the given updated value if the current value {@code ==} the
    122      * expected value. This method is guaranteed to be atomic with respect to
    123      * other calls to {@code compareAndSet} and {@code set}, but not
    124      * necessarily with respect to other changes in the field.
    125      *
    126      * @param obj An object whose field to conditionally set
    127      * @param expect the expected value
    128      * @param update the new value
    129      * @return {@code true} if successful
    130      */
    131     public abstract boolean compareAndSet(T obj, V expect, V update);
    132 
    133     /**
    134      * Atomically sets the field of the given object managed by this updater
    135      * to the given updated value if the current value {@code ==} the
    136      * expected value. This method is guaranteed to be atomic with respect to
    137      * other calls to {@code compareAndSet} and {@code set}, but not
    138      * necessarily with respect to other changes in the field.
    139      *
    140      * <p><a href="package-summary.html#weakCompareAndSet">May fail
    141      * spuriously and does not provide ordering guarantees</a>, so is
    142      * only rarely an appropriate alternative to {@code compareAndSet}.
    143      *
    144      * @param obj An object whose field to conditionally set
    145      * @param expect the expected value
    146      * @param update the new value
    147      * @return {@code true} if successful
    148      */
    149     public abstract boolean weakCompareAndSet(T obj, V expect, V update);
    150 
    151     /**
    152      * Sets the field of the given object managed by this updater to the
    153      * given updated value. This operation is guaranteed to act as a volatile
    154      * store with respect to subsequent invocations of {@code compareAndSet}.
    155      *
    156      * @param obj An object whose field to set
    157      * @param newValue the new value
    158      */
    159     public abstract void set(T obj, V newValue);
    160 
    161     /**
    162      * Eventually sets the field of the given object managed by this
    163      * updater to the given updated value.
    164      *
    165      * @param obj An object whose field to set
    166      * @param newValue the new value
    167      * @since 1.6
    168      */
    169     public abstract void lazySet(T obj, V newValue);
    170 
    171     /**
    172      * Gets the current value held in the field of the given object managed
    173      * by this updater.
    174      *
    175      * @param obj An object whose field to get
    176      * @return the current value
    177      */
    178     public abstract V get(T obj);
    179 
    180     /**
    181      * Atomically sets the field of the given object managed by this updater
    182      * to the given value and returns the old value.
    183      *
    184      * @param obj An object whose field to get and set
    185      * @param newValue the new value
    186      * @return the previous value
    187      */
    188     public V getAndSet(T obj, V newValue) {
    189         V prev;
    190         do {
    191             prev = get(obj);
    192         } while (!compareAndSet(obj, prev, newValue));
    193         return prev;
    194     }
    195 
    196     /**
    197      * Atomically updates the field of the given object managed by this updater
    198      * with the results of applying the given function, returning the previous
    199      * value. The function should be side-effect-free, since it may be
    200      * re-applied when attempted updates fail due to contention among threads.
    201      *
    202      * @param obj An object whose field to get and set
    203      * @param updateFunction a side-effect-free function
    204      * @return the previous value
    205      * @since 1.8
    206      */
    207     public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) {
    208         V prev, next;
    209         do {
    210             prev = get(obj);
    211             next = updateFunction.apply(prev);
    212         } while (!compareAndSet(obj, prev, next));
    213         return prev;
    214     }
    215 
    216     /**
    217      * Atomically updates the field of the given object managed by this updater
    218      * with the results of applying the given function, returning the updated
    219      * value. The function should be side-effect-free, since it may be
    220      * re-applied when attempted updates fail due to contention among threads.
    221      *
    222      * @param obj An object whose field to get and set
    223      * @param updateFunction a side-effect-free function
    224      * @return the updated value
    225      * @since 1.8
    226      */
    227     public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) {
    228         V prev, next;
    229         do {
    230             prev = get(obj);
    231             next = updateFunction.apply(prev);
    232         } while (!compareAndSet(obj, prev, next));
    233         return next;
    234     }
    235 
    236     /**
    237      * Atomically updates the field of the given object managed by this
    238      * updater with the results of applying the given function to the
    239      * current and given values, returning the previous value. The
    240      * function should be side-effect-free, since it may be re-applied
    241      * when attempted updates fail due to contention among threads.  The
    242      * function is applied with the current value as its first argument,
    243      * and the given update as the second argument.
    244      *
    245      * @param obj An object whose field to get and set
    246      * @param x the update value
    247      * @param accumulatorFunction a side-effect-free function of two arguments
    248      * @return the previous value
    249      * @since 1.8
    250      */
    251     public final V getAndAccumulate(T obj, V x,
    252                                     BinaryOperator<V> accumulatorFunction) {
    253         V prev, next;
    254         do {
    255             prev = get(obj);
    256             next = accumulatorFunction.apply(prev, x);
    257         } while (!compareAndSet(obj, prev, next));
    258         return prev;
    259     }
    260 
    261     /**
    262      * Atomically updates the field of the given object managed by this
    263      * updater with the results of applying the given function to the
    264      * current and given values, returning the updated value. The
    265      * function should be side-effect-free, since it may be re-applied
    266      * when attempted updates fail due to contention among threads.  The
    267      * function is applied with the current value as its first argument,
    268      * and the given update as the second argument.
    269      *
    270      * @param obj An object whose field to get and set
    271      * @param x the update value
    272      * @param accumulatorFunction a side-effect-free function of two arguments
    273      * @return the updated value
    274      * @since 1.8
    275      */
    276     public final V accumulateAndGet(T obj, V x,
    277                                     BinaryOperator<V> accumulatorFunction) {
    278         V prev, next;
    279         do {
    280             prev = get(obj);
    281             next = accumulatorFunction.apply(prev, x);
    282         } while (!compareAndSet(obj, prev, next));
    283         return next;
    284     }
    285 
    286     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
    287         extends AtomicReferenceFieldUpdater<T,V> {
    288         private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
    289         private final long offset;
    290         /**
    291          * if field is protected, the subclass constructing updater, else
    292          * the same as tclass
    293          */
    294         private final Class<?> cclass;
    295         /** class holding the field */
    296         private final Class<T> tclass;
    297         /** field value type */
    298         private final Class<V> vclass;
    299 
    300         /*
    301          * Internal type checks within all update methods contain
    302          * internal inlined optimizations checking for the common
    303          * cases where the class is final (in which case a simple
    304          * getClass comparison suffices) or is of type Object (in
    305          * which case no check is needed because all objects are
    306          * instances of Object). The Object case is handled simply by
    307          * setting vclass to null in constructor.  The targetCheck and
    308          * updateCheck methods are invoked when these faster
    309          * screenings fail.
    310          */
    311 
    312         AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
    313                                         final Class<V> vclass,
    314                                         final String fieldName,
    315                                         final Class<?> caller) {
    316             final Field field;
    317             final Class<?> fieldClass;
    318             final int modifiers;
    319             try {
    320                 field = tclass.getDeclaredField(fieldName); // Android-changed
    321                 modifiers = field.getModifiers();
    322                 // BEGIN Android-removed
    323                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
    324                 //     caller, tclass, null, modifiers);
    325                 // ClassLoader cl = tclass.getClassLoader();
    326                 // ClassLoader ccl = caller.getClassLoader();
    327                 // if ((ccl != null) && (ccl != cl) &&
    328                 //     ((cl == null) || !isAncestor(cl, ccl))) {
    329                 //     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
    330                 // }
    331                 // END Android-removed
    332                 fieldClass = field.getType();
    333             // BEGIN Android-removed
    334             // } catch (PrivilegedActionException pae) {
    335             //     throw new RuntimeException(pae.getException());
    336             // END Android-removed
    337             } catch (Exception ex) {
    338                 throw new RuntimeException(ex);
    339             }
    340 
    341             if (vclass != fieldClass)
    342                 throw new ClassCastException();
    343             if (vclass.isPrimitive())
    344                 throw new IllegalArgumentException("Must be reference type");
    345 
    346             if (!Modifier.isVolatile(modifiers))
    347                 throw new IllegalArgumentException("Must be volatile type");
    348 
    349             this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
    350             this.tclass = tclass;
    351             this.vclass = vclass;
    352             this.offset = U.objectFieldOffset(field);
    353         }
    354 
    355         // BEGIN Android-removed
    356         // /**
    357         //  * Returns true if the second classloader can be found in the first
    358         //  * classloader's delegation chain.
    359         //  * Equivalent to the inaccessible: first.isAncestor(second).
    360         //  */
    361         // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
    362         //     ClassLoader acl = first;
    363         //     do {
    364         //         acl = acl.getParent();
    365         //         if (second == acl) {
    366         //             return true;
    367         //         }
    368         //     } while (acl != null);
    369         //     return false;
    370         // }
    371         // END Android-removed
    372 
    373         /**
    374          * Checks that target argument is instance of cclass.  On
    375          * failure, throws cause.
    376          */
    377         private final void accessCheck(T obj) {
    378             if (!cclass.isInstance(obj))
    379                 throwAccessCheckException(obj);
    380         }
    381 
    382         /**
    383          * Throws access exception if accessCheck failed due to
    384          * protected access, else ClassCastException.
    385          */
    386         private final void throwAccessCheckException(T obj) {
    387             if (cclass == tclass)
    388                 throw new ClassCastException();
    389             else
    390                 throw new RuntimeException(
    391                     new IllegalAccessException(
    392                         "Class " +
    393                         cclass.getName() +
    394                         " can not access a protected member of class " +
    395                         tclass.getName() +
    396                         " using an instance of " +
    397                         obj.getClass().getName()));
    398         }
    399 
    400         private final void valueCheck(V v) {
    401             if (v != null && !(vclass.isInstance(v)))
    402                 throwCCE();
    403         }
    404 
    405         static void throwCCE() {
    406             throw new ClassCastException();
    407         }
    408 
    409         public final boolean compareAndSet(T obj, V expect, V update) {
    410             accessCheck(obj);
    411             valueCheck(update);
    412             return U.compareAndSwapObject(obj, offset, expect, update);
    413         }
    414 
    415         public final boolean weakCompareAndSet(T obj, V expect, V update) {
    416             // same implementation as strong form for now
    417             accessCheck(obj);
    418             valueCheck(update);
    419             return U.compareAndSwapObject(obj, offset, expect, update);
    420         }
    421 
    422         public final void set(T obj, V newValue) {
    423             accessCheck(obj);
    424             valueCheck(newValue);
    425             U.putObjectVolatile(obj, offset, newValue);
    426         }
    427 
    428         public final void lazySet(T obj, V newValue) {
    429             accessCheck(obj);
    430             valueCheck(newValue);
    431             U.putOrderedObject(obj, offset, newValue);
    432         }
    433 
    434         @SuppressWarnings("unchecked")
    435         public final V get(T obj) {
    436             accessCheck(obj);
    437             return (V)U.getObjectVolatile(obj, offset);
    438         }
    439 
    440         @SuppressWarnings("unchecked")
    441         public final V getAndSet(T obj, V newValue) {
    442             accessCheck(obj);
    443             valueCheck(newValue);
    444             return (V)U.getAndSetObject(obj, offset, newValue);
    445         }
    446     }
    447 }
    448