Merging in new JDK classes for emulation: Updaters
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 09 Feb 2015 20:32:36 +0100
changeset 1778f0c5b36d9311
parent 1777 f19e2fe0855a
parent 1776 b208ff5b7dbc
child 1779 9d757281c666
Merging in new JDK classes for emulation: Updaters
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Mon Feb 09 20:32:36 2015 +0100
     1.3 @@ -0,0 +1,346 @@
     1.4 +/*
     1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.6 + *
     1.7 + * This code is free software; you can redistribute it and/or modify it
     1.8 + * under the terms of the GNU General Public License version 2 only, as
     1.9 + * published by the Free Software Foundation.  Oracle designates this
    1.10 + * particular file as subject to the "Classpath" exception as provided
    1.11 + * by Oracle in the LICENSE file that accompanied this code.
    1.12 + *
    1.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.16 + * version 2 for more details (a copy is included in the LICENSE file that
    1.17 + * accompanied this code).
    1.18 + *
    1.19 + * You should have received a copy of the GNU General Public License version
    1.20 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.22 + *
    1.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.24 + * or visit www.oracle.com if you need additional information or have any
    1.25 + * questions.
    1.26 + */
    1.27 +
    1.28 +/*
    1.29 + * This file is available under and governed by the GNU General Public
    1.30 + * License version 2 only, as published by the Free Software Foundation.
    1.31 + * However, the following notice accompanied the original version of this
    1.32 + * file:
    1.33 + *
    1.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
    1.35 + * Expert Group and released to the public domain, as explained at
    1.36 + * http://creativecommons.org/publicdomain/zero/1.0/
    1.37 + */
    1.38 +
    1.39 +package java.util.concurrent.atomic;
    1.40 +import sun.misc.Unsafe;
    1.41 +import java.lang.reflect.*;
    1.42 +
    1.43 +/**
    1.44 + * A reflection-based utility that enables atomic updates to
    1.45 + * designated {@code volatile int} fields of designated classes.
    1.46 + * This class is designed for use in atomic data structures in which
    1.47 + * several fields of the same node are independently subject to atomic
    1.48 + * updates.
    1.49 + *
    1.50 + * <p>Note that the guarantees of the {@code compareAndSet}
    1.51 + * method in this class are weaker than in other atomic classes.
    1.52 + * Because this class cannot ensure that all uses of the field
    1.53 + * are appropriate for purposes of atomic access, it can
    1.54 + * guarantee atomicity only with respect to other invocations of
    1.55 + * {@code compareAndSet} and {@code set} on the same updater.
    1.56 + *
    1.57 + * @since 1.5
    1.58 + * @author Doug Lea
    1.59 + * @param <T> The type of the object holding the updatable field
    1.60 + */
    1.61 +public abstract class  AtomicIntegerFieldUpdater<T> {
    1.62 +    /**
    1.63 +     * Creates and returns an updater for objects with the given field.
    1.64 +     * The Class argument is needed to check that reflective types and
    1.65 +     * generic types match.
    1.66 +     *
    1.67 +     * @param tclass the class of the objects holding the field
    1.68 +     * @param fieldName the name of the field to be updated
    1.69 +     * @return the updater
    1.70 +     * @throws IllegalArgumentException if the field is not a
    1.71 +     * volatile integer type
    1.72 +     * @throws RuntimeException with a nested reflection-based
    1.73 +     * exception if the class does not hold field or is the wrong type
    1.74 +     */
    1.75 +    public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
    1.76 +        return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
    1.77 +    }
    1.78 +
    1.79 +    /**
    1.80 +     * Protected do-nothing constructor for use by subclasses.
    1.81 +     */
    1.82 +    protected AtomicIntegerFieldUpdater() {
    1.83 +    }
    1.84 +
    1.85 +    /**
    1.86 +     * Atomically sets the field of the given object managed by this updater
    1.87 +     * to the given updated value if the current value {@code ==} the
    1.88 +     * expected value. This method is guaranteed to be atomic with respect to
    1.89 +     * other calls to {@code compareAndSet} and {@code set}, but not
    1.90 +     * necessarily with respect to other changes in the field.
    1.91 +     *
    1.92 +     * @param obj An object whose field to conditionally set
    1.93 +     * @param expect the expected value
    1.94 +     * @param update the new value
    1.95 +     * @return true if successful
    1.96 +     * @throws ClassCastException if {@code obj} is not an instance
    1.97 +     * of the class possessing the field established in the constructor
    1.98 +     */
    1.99 +    public abstract boolean compareAndSet(T obj, int expect, int update);
   1.100 +
   1.101 +    /**
   1.102 +     * Atomically sets the field of the given object managed by this updater
   1.103 +     * to the given updated value if the current value {@code ==} the
   1.104 +     * expected value. This method is guaranteed to be atomic with respect to
   1.105 +     * other calls to {@code compareAndSet} and {@code set}, but not
   1.106 +     * necessarily with respect to other changes in the field.
   1.107 +     *
   1.108 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
   1.109 +     * and does not provide ordering guarantees, so is only rarely an
   1.110 +     * appropriate alternative to {@code compareAndSet}.
   1.111 +     *
   1.112 +     * @param obj An object whose field to conditionally set
   1.113 +     * @param expect the expected value
   1.114 +     * @param update the new value
   1.115 +     * @return true if successful
   1.116 +     * @throws ClassCastException if {@code obj} is not an instance
   1.117 +     * of the class possessing the field established in the constructor
   1.118 +     */
   1.119 +    public abstract boolean weakCompareAndSet(T obj, int expect, int update);
   1.120 +
   1.121 +    /**
   1.122 +     * Sets the field of the given object managed by this updater to the
   1.123 +     * given updated value. This operation is guaranteed to act as a volatile
   1.124 +     * store with respect to subsequent invocations of {@code compareAndSet}.
   1.125 +     *
   1.126 +     * @param obj An object whose field to set
   1.127 +     * @param newValue the new value
   1.128 +     */
   1.129 +    public abstract void set(T obj, int newValue);
   1.130 +
   1.131 +    /**
   1.132 +     * Eventually sets the field of the given object managed by this
   1.133 +     * updater to the given updated value.
   1.134 +     *
   1.135 +     * @param obj An object whose field to set
   1.136 +     * @param newValue the new value
   1.137 +     * @since 1.6
   1.138 +     */
   1.139 +    public abstract void lazySet(T obj, int newValue);
   1.140 +
   1.141 +
   1.142 +    /**
   1.143 +     * Gets the current value held in the field of the given object managed
   1.144 +     * by this updater.
   1.145 +     *
   1.146 +     * @param obj An object whose field to get
   1.147 +     * @return the current value
   1.148 +     */
   1.149 +    public abstract int get(T obj);
   1.150 +
   1.151 +    /**
   1.152 +     * Atomically sets the field of the given object managed by this updater
   1.153 +     * to the given value and returns the old value.
   1.154 +     *
   1.155 +     * @param obj An object whose field to get and set
   1.156 +     * @param newValue the new value
   1.157 +     * @return the previous value
   1.158 +     */
   1.159 +    public int getAndSet(T obj, int newValue) {
   1.160 +        for (;;) {
   1.161 +            int current = get(obj);
   1.162 +            if (compareAndSet(obj, current, newValue))
   1.163 +                return current;
   1.164 +        }
   1.165 +    }
   1.166 +
   1.167 +    /**
   1.168 +     * Atomically increments by one the current value of the field of the
   1.169 +     * given object managed by this updater.
   1.170 +     *
   1.171 +     * @param obj An object whose field to get and set
   1.172 +     * @return the previous value
   1.173 +     */
   1.174 +    public int getAndIncrement(T obj) {
   1.175 +        for (;;) {
   1.176 +            int current = get(obj);
   1.177 +            int next = current + 1;
   1.178 +            if (compareAndSet(obj, current, next))
   1.179 +                return current;
   1.180 +        }
   1.181 +    }
   1.182 +
   1.183 +    /**
   1.184 +     * Atomically decrements by one the current value of the field of the
   1.185 +     * given object managed by this updater.
   1.186 +     *
   1.187 +     * @param obj An object whose field to get and set
   1.188 +     * @return the previous value
   1.189 +     */
   1.190 +    public int getAndDecrement(T obj) {
   1.191 +        for (;;) {
   1.192 +            int current = get(obj);
   1.193 +            int next = current - 1;
   1.194 +            if (compareAndSet(obj, current, next))
   1.195 +                return current;
   1.196 +        }
   1.197 +    }
   1.198 +
   1.199 +    /**
   1.200 +     * Atomically adds the given value to the current value of the field of
   1.201 +     * the given object managed by this updater.
   1.202 +     *
   1.203 +     * @param obj An object whose field to get and set
   1.204 +     * @param delta the value to add
   1.205 +     * @return the previous value
   1.206 +     */
   1.207 +    public int getAndAdd(T obj, int delta) {
   1.208 +        for (;;) {
   1.209 +            int current = get(obj);
   1.210 +            int next = current + delta;
   1.211 +            if (compareAndSet(obj, current, next))
   1.212 +                return current;
   1.213 +        }
   1.214 +    }
   1.215 +
   1.216 +    /**
   1.217 +     * Atomically increments by one the current value of the field of the
   1.218 +     * given object managed by this updater.
   1.219 +     *
   1.220 +     * @param obj An object whose field to get and set
   1.221 +     * @return the updated value
   1.222 +     */
   1.223 +    public int incrementAndGet(T obj) {
   1.224 +        for (;;) {
   1.225 +            int current = get(obj);
   1.226 +            int next = current + 1;
   1.227 +            if (compareAndSet(obj, current, next))
   1.228 +                return next;
   1.229 +        }
   1.230 +    }
   1.231 +
   1.232 +    /**
   1.233 +     * Atomically decrements by one the current value of the field of the
   1.234 +     * given object managed by this updater.
   1.235 +     *
   1.236 +     * @param obj An object whose field to get and set
   1.237 +     * @return the updated value
   1.238 +     */
   1.239 +    public int decrementAndGet(T obj) {
   1.240 +        for (;;) {
   1.241 +            int current = get(obj);
   1.242 +            int next = current - 1;
   1.243 +            if (compareAndSet(obj, current, next))
   1.244 +                return next;
   1.245 +        }
   1.246 +    }
   1.247 +
   1.248 +    /**
   1.249 +     * Atomically adds the given value to the current value of the field of
   1.250 +     * the given object managed by this updater.
   1.251 +     *
   1.252 +     * @param obj An object whose field to get and set
   1.253 +     * @param delta the value to add
   1.254 +     * @return the updated value
   1.255 +     */
   1.256 +    public int addAndGet(T obj, int delta) {
   1.257 +        for (;;) {
   1.258 +            int current = get(obj);
   1.259 +            int next = current + delta;
   1.260 +            if (compareAndSet(obj, current, next))
   1.261 +                return next;
   1.262 +        }
   1.263 +    }
   1.264 +
   1.265 +    /**
   1.266 +     * Standard hotspot implementation using intrinsics
   1.267 +     */
   1.268 +    private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
   1.269 +        private static final Unsafe unsafe = Unsafe.getUnsafe();
   1.270 +        private final long offset;
   1.271 +        private final Class<T> tclass;
   1.272 +        private final Class cclass;
   1.273 +
   1.274 +        AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
   1.275 +            Field field = null;
   1.276 +            Class caller = null;
   1.277 +            int modifiers = 0;
   1.278 +            try {
   1.279 +                field = tclass.getDeclaredField(fieldName);
   1.280 +                caller = sun.reflect.Reflection.getCallerClass(3);
   1.281 +                modifiers = field.getModifiers();
   1.282 +                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
   1.283 +                    caller, tclass, null, modifiers);
   1.284 +                sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
   1.285 +            } catch (Exception ex) {
   1.286 +                throw new RuntimeException(ex);
   1.287 +            }
   1.288 +
   1.289 +            Class fieldt = field.getType();
   1.290 +            if (fieldt != int.class)
   1.291 +                throw new IllegalArgumentException("Must be integer type");
   1.292 +
   1.293 +            if (!Modifier.isVolatile(modifiers))
   1.294 +                throw new IllegalArgumentException("Must be volatile type");
   1.295 +
   1.296 +            this.cclass = (Modifier.isProtected(modifiers) &&
   1.297 +                           caller != tclass) ? caller : null;
   1.298 +            this.tclass = tclass;
   1.299 +            offset = unsafe.objectFieldOffset(field);
   1.300 +        }
   1.301 +
   1.302 +        private void fullCheck(T obj) {
   1.303 +            if (!tclass.isInstance(obj))
   1.304 +                throw new ClassCastException();
   1.305 +            if (cclass != null)
   1.306 +                ensureProtectedAccess(obj);
   1.307 +        }
   1.308 +
   1.309 +        public boolean compareAndSet(T obj, int expect, int update) {
   1.310 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   1.311 +            return unsafe.compareAndSwapInt(obj, offset, expect, update);
   1.312 +        }
   1.313 +
   1.314 +        public boolean weakCompareAndSet(T obj, int expect, int update) {
   1.315 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   1.316 +            return unsafe.compareAndSwapInt(obj, offset, expect, update);
   1.317 +        }
   1.318 +
   1.319 +        public void set(T obj, int newValue) {
   1.320 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   1.321 +            unsafe.putIntVolatile(obj, offset, newValue);
   1.322 +        }
   1.323 +
   1.324 +        public void lazySet(T obj, int newValue) {
   1.325 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   1.326 +            unsafe.putOrderedInt(obj, offset, newValue);
   1.327 +        }
   1.328 +
   1.329 +        public final int get(T obj) {
   1.330 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   1.331 +            return unsafe.getIntVolatile(obj, offset);
   1.332 +        }
   1.333 +
   1.334 +        private void ensureProtectedAccess(T obj) {
   1.335 +            if (cclass.isInstance(obj)) {
   1.336 +                return;
   1.337 +            }
   1.338 +            throw new RuntimeException(
   1.339 +                new IllegalAccessException("Class " +
   1.340 +                    cclass.getName() +
   1.341 +                    " can not access a protected member of class " +
   1.342 +                    tclass.getName() +
   1.343 +                    " using an instance of " +
   1.344 +                    obj.getClass().getName()
   1.345 +                )
   1.346 +            );
   1.347 +        }
   1.348 +    }
   1.349 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Mon Feb 09 20:32:36 2015 +0100
     2.3 @@ -0,0 +1,436 @@
     2.4 +/*
     2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.6 + *
     2.7 + * This code is free software; you can redistribute it and/or modify it
     2.8 + * under the terms of the GNU General Public License version 2 only, as
     2.9 + * published by the Free Software Foundation.  Oracle designates this
    2.10 + * particular file as subject to the "Classpath" exception as provided
    2.11 + * by Oracle in the LICENSE file that accompanied this code.
    2.12 + *
    2.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.16 + * version 2 for more details (a copy is included in the LICENSE file that
    2.17 + * accompanied this code).
    2.18 + *
    2.19 + * You should have received a copy of the GNU General Public License version
    2.20 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.22 + *
    2.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.24 + * or visit www.oracle.com if you need additional information or have any
    2.25 + * questions.
    2.26 + */
    2.27 +
    2.28 +/*
    2.29 + * This file is available under and governed by the GNU General Public
    2.30 + * License version 2 only, as published by the Free Software Foundation.
    2.31 + * However, the following notice accompanied the original version of this
    2.32 + * file:
    2.33 + *
    2.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
    2.35 + * Expert Group and released to the public domain, as explained at
    2.36 + * http://creativecommons.org/publicdomain/zero/1.0/
    2.37 + */
    2.38 +
    2.39 +package java.util.concurrent.atomic;
    2.40 +import sun.misc.Unsafe;
    2.41 +import java.lang.reflect.*;
    2.42 +
    2.43 +/**
    2.44 + * A reflection-based utility that enables atomic updates to
    2.45 + * designated {@code volatile long} fields of designated classes.
    2.46 + * This class is designed for use in atomic data structures in which
    2.47 + * several fields of the same node are independently subject to atomic
    2.48 + * updates.
    2.49 + *
    2.50 + * <p>Note that the guarantees of the {@code compareAndSet}
    2.51 + * method in this class are weaker than in other atomic classes.
    2.52 + * Because this class cannot ensure that all uses of the field
    2.53 + * are appropriate for purposes of atomic access, it can
    2.54 + * guarantee atomicity only with respect to other invocations of
    2.55 + * {@code compareAndSet} and {@code set} on the same updater.
    2.56 + *
    2.57 + * @since 1.5
    2.58 + * @author Doug Lea
    2.59 + * @param <T> The type of the object holding the updatable field
    2.60 + */
    2.61 +public abstract class  AtomicLongFieldUpdater<T> {
    2.62 +    /**
    2.63 +     * Creates and returns an updater for objects with the given field.
    2.64 +     * The Class argument is needed to check that reflective types and
    2.65 +     * generic types match.
    2.66 +     *
    2.67 +     * @param tclass the class of the objects holding the field
    2.68 +     * @param fieldName the name of the field to be updated.
    2.69 +     * @return the updater
    2.70 +     * @throws IllegalArgumentException if the field is not a
    2.71 +     * volatile long type.
    2.72 +     * @throws RuntimeException with a nested reflection-based
    2.73 +     * exception if the class does not hold field or is the wrong type.
    2.74 +     */
    2.75 +    public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
    2.76 +        if (AtomicLong.VM_SUPPORTS_LONG_CAS)
    2.77 +            return new CASUpdater<U>(tclass, fieldName);
    2.78 +        else
    2.79 +            return new LockedUpdater<U>(tclass, fieldName);
    2.80 +    }
    2.81 +
    2.82 +    /**
    2.83 +     * Protected do-nothing constructor for use by subclasses.
    2.84 +     */
    2.85 +    protected AtomicLongFieldUpdater() {
    2.86 +    }
    2.87 +
    2.88 +    /**
    2.89 +     * Atomically sets the field of the given object managed by this updater
    2.90 +     * to the given updated value if the current value {@code ==} the
    2.91 +     * expected value. This method is guaranteed to be atomic with respect to
    2.92 +     * other calls to {@code compareAndSet} and {@code set}, but not
    2.93 +     * necessarily with respect to other changes in the field.
    2.94 +     *
    2.95 +     * @param obj An object whose field to conditionally set
    2.96 +     * @param expect the expected value
    2.97 +     * @param update the new value
    2.98 +     * @return true if successful.
    2.99 +     * @throws ClassCastException if {@code obj} is not an instance
   2.100 +     * of the class possessing the field established in the constructor.
   2.101 +     */
   2.102 +    public abstract boolean compareAndSet(T obj, long expect, long update);
   2.103 +
   2.104 +    /**
   2.105 +     * Atomically sets the field of the given object managed by this updater
   2.106 +     * to the given updated value if the current value {@code ==} the
   2.107 +     * expected value. This method is guaranteed to be atomic with respect to
   2.108 +     * other calls to {@code compareAndSet} and {@code set}, but not
   2.109 +     * necessarily with respect to other changes in the field.
   2.110 +     *
   2.111 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
   2.112 +     * and does not provide ordering guarantees, so is only rarely an
   2.113 +     * appropriate alternative to {@code compareAndSet}.
   2.114 +     *
   2.115 +     * @param obj An object whose field to conditionally set
   2.116 +     * @param expect the expected value
   2.117 +     * @param update the new value
   2.118 +     * @return true if successful.
   2.119 +     * @throws ClassCastException if {@code obj} is not an instance
   2.120 +     * of the class possessing the field established in the constructor.
   2.121 +     */
   2.122 +    public abstract boolean weakCompareAndSet(T obj, long expect, long update);
   2.123 +
   2.124 +    /**
   2.125 +     * Sets the field of the given object managed by this updater to the
   2.126 +     * given updated value. This operation is guaranteed to act as a volatile
   2.127 +     * store with respect to subsequent invocations of {@code compareAndSet}.
   2.128 +     *
   2.129 +     * @param obj An object whose field to set
   2.130 +     * @param newValue the new value
   2.131 +     */
   2.132 +    public abstract void set(T obj, long newValue);
   2.133 +
   2.134 +    /**
   2.135 +     * Eventually sets the field of the given object managed by this
   2.136 +     * updater to the given updated value.
   2.137 +     *
   2.138 +     * @param obj An object whose field to set
   2.139 +     * @param newValue the new value
   2.140 +     * @since 1.6
   2.141 +     */
   2.142 +    public abstract void lazySet(T obj, long newValue);
   2.143 +
   2.144 +    /**
   2.145 +     * Gets the current value held in the field of the given object managed
   2.146 +     * by this updater.
   2.147 +     *
   2.148 +     * @param obj An object whose field to get
   2.149 +     * @return the current value
   2.150 +     */
   2.151 +    public abstract long get(T obj);
   2.152 +
   2.153 +    /**
   2.154 +     * Atomically sets the field of the given object managed by this updater
   2.155 +     * to the given value and returns the old value.
   2.156 +     *
   2.157 +     * @param obj An object whose field to get and set
   2.158 +     * @param newValue the new value
   2.159 +     * @return the previous value
   2.160 +     */
   2.161 +    public long getAndSet(T obj, long newValue) {
   2.162 +        for (;;) {
   2.163 +            long current = get(obj);
   2.164 +            if (compareAndSet(obj, current, newValue))
   2.165 +                return current;
   2.166 +        }
   2.167 +    }
   2.168 +
   2.169 +    /**
   2.170 +     * Atomically increments by one the current value of the field of the
   2.171 +     * given object managed by this updater.
   2.172 +     *
   2.173 +     * @param obj An object whose field to get and set
   2.174 +     * @return the previous value
   2.175 +     */
   2.176 +    public long getAndIncrement(T obj) {
   2.177 +        for (;;) {
   2.178 +            long current = get(obj);
   2.179 +            long next = current + 1;
   2.180 +            if (compareAndSet(obj, current, next))
   2.181 +                return current;
   2.182 +        }
   2.183 +    }
   2.184 +
   2.185 +    /**
   2.186 +     * Atomically decrements by one the current value of the field of the
   2.187 +     * given object managed by this updater.
   2.188 +     *
   2.189 +     * @param obj An object whose field to get and set
   2.190 +     * @return the previous value
   2.191 +     */
   2.192 +    public long getAndDecrement(T obj) {
   2.193 +        for (;;) {
   2.194 +            long current = get(obj);
   2.195 +            long next = current - 1;
   2.196 +            if (compareAndSet(obj, current, next))
   2.197 +                return current;
   2.198 +        }
   2.199 +    }
   2.200 +
   2.201 +    /**
   2.202 +     * Atomically adds the given value to the current value of the field of
   2.203 +     * the given object managed by this updater.
   2.204 +     *
   2.205 +     * @param obj An object whose field to get and set
   2.206 +     * @param delta the value to add
   2.207 +     * @return the previous value
   2.208 +     */
   2.209 +    public long getAndAdd(T obj, long delta) {
   2.210 +        for (;;) {
   2.211 +            long current = get(obj);
   2.212 +            long next = current + delta;
   2.213 +            if (compareAndSet(obj, current, next))
   2.214 +                return current;
   2.215 +        }
   2.216 +    }
   2.217 +
   2.218 +    /**
   2.219 +     * Atomically increments by one the current value of the field of the
   2.220 +     * given object managed by this updater.
   2.221 +     *
   2.222 +     * @param obj An object whose field to get and set
   2.223 +     * @return the updated value
   2.224 +     */
   2.225 +    public long incrementAndGet(T obj) {
   2.226 +        for (;;) {
   2.227 +            long current = get(obj);
   2.228 +            long next = current + 1;
   2.229 +            if (compareAndSet(obj, current, next))
   2.230 +                return next;
   2.231 +        }
   2.232 +    }
   2.233 +
   2.234 +    /**
   2.235 +     * Atomically decrements by one the current value of the field of the
   2.236 +     * given object managed by this updater.
   2.237 +     *
   2.238 +     * @param obj An object whose field to get and set
   2.239 +     * @return the updated value
   2.240 +     */
   2.241 +    public long decrementAndGet(T obj) {
   2.242 +        for (;;) {
   2.243 +            long current = get(obj);
   2.244 +            long next = current - 1;
   2.245 +            if (compareAndSet(obj, current, next))
   2.246 +                return next;
   2.247 +        }
   2.248 +    }
   2.249 +
   2.250 +    /**
   2.251 +     * Atomically adds the given value to the current value of the field of
   2.252 +     * the given object managed by this updater.
   2.253 +     *
   2.254 +     * @param obj An object whose field to get and set
   2.255 +     * @param delta the value to add
   2.256 +     * @return the updated value
   2.257 +     */
   2.258 +    public long addAndGet(T obj, long delta) {
   2.259 +        for (;;) {
   2.260 +            long current = get(obj);
   2.261 +            long next = current + delta;
   2.262 +            if (compareAndSet(obj, current, next))
   2.263 +                return next;
   2.264 +        }
   2.265 +    }
   2.266 +
   2.267 +    private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
   2.268 +        private static final Unsafe unsafe = Unsafe.getUnsafe();
   2.269 +        private final long offset;
   2.270 +        private final Class<T> tclass;
   2.271 +        private final Class cclass;
   2.272 +
   2.273 +        CASUpdater(Class<T> tclass, String fieldName) {
   2.274 +            Field field = null;
   2.275 +            Class caller = null;
   2.276 +            int modifiers = 0;
   2.277 +            try {
   2.278 +                field = tclass.getDeclaredField(fieldName);
   2.279 +                caller = sun.reflect.Reflection.getCallerClass(3);
   2.280 +                modifiers = field.getModifiers();
   2.281 +                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
   2.282 +                    caller, tclass, null, modifiers);
   2.283 +                sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
   2.284 +            } catch (Exception ex) {
   2.285 +                throw new RuntimeException(ex);
   2.286 +            }
   2.287 +
   2.288 +            Class fieldt = field.getType();
   2.289 +            if (fieldt != long.class)
   2.290 +                throw new IllegalArgumentException("Must be long type");
   2.291 +
   2.292 +            if (!Modifier.isVolatile(modifiers))
   2.293 +                throw new IllegalArgumentException("Must be volatile type");
   2.294 +
   2.295 +            this.cclass = (Modifier.isProtected(modifiers) &&
   2.296 +                           caller != tclass) ? caller : null;
   2.297 +            this.tclass = tclass;
   2.298 +            offset = unsafe.objectFieldOffset(field);
   2.299 +        }
   2.300 +
   2.301 +        private void fullCheck(T obj) {
   2.302 +            if (!tclass.isInstance(obj))
   2.303 +                throw new ClassCastException();
   2.304 +            if (cclass != null)
   2.305 +                ensureProtectedAccess(obj);
   2.306 +        }
   2.307 +
   2.308 +        public boolean compareAndSet(T obj, long expect, long update) {
   2.309 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.310 +            return unsafe.compareAndSwapLong(obj, offset, expect, update);
   2.311 +        }
   2.312 +
   2.313 +        public boolean weakCompareAndSet(T obj, long expect, long update) {
   2.314 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.315 +            return unsafe.compareAndSwapLong(obj, offset, expect, update);
   2.316 +        }
   2.317 +
   2.318 +        public void set(T obj, long newValue) {
   2.319 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.320 +            unsafe.putLongVolatile(obj, offset, newValue);
   2.321 +        }
   2.322 +
   2.323 +        public void lazySet(T obj, long newValue) {
   2.324 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.325 +            unsafe.putOrderedLong(obj, offset, newValue);
   2.326 +        }
   2.327 +
   2.328 +        public long get(T obj) {
   2.329 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.330 +            return unsafe.getLongVolatile(obj, offset);
   2.331 +        }
   2.332 +
   2.333 +        private void ensureProtectedAccess(T obj) {
   2.334 +            if (cclass.isInstance(obj)) {
   2.335 +                return;
   2.336 +            }
   2.337 +            throw new RuntimeException(
   2.338 +                new IllegalAccessException("Class " +
   2.339 +                    cclass.getName() +
   2.340 +                    " can not access a protected member of class " +
   2.341 +                    tclass.getName() +
   2.342 +                    " using an instance of " +
   2.343 +                    obj.getClass().getName()
   2.344 +                )
   2.345 +            );
   2.346 +        }
   2.347 +    }
   2.348 +
   2.349 +
   2.350 +    private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
   2.351 +        private static final Unsafe unsafe = Unsafe.getUnsafe();
   2.352 +        private final long offset;
   2.353 +        private final Class<T> tclass;
   2.354 +        private final Class cclass;
   2.355 +
   2.356 +        LockedUpdater(Class<T> tclass, String fieldName) {
   2.357 +            Field field = null;
   2.358 +            Class caller = null;
   2.359 +            int modifiers = 0;
   2.360 +            try {
   2.361 +                field = tclass.getDeclaredField(fieldName);
   2.362 +                caller = sun.reflect.Reflection.getCallerClass(3);
   2.363 +                modifiers = field.getModifiers();
   2.364 +                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
   2.365 +                    caller, tclass, null, modifiers);
   2.366 +                sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
   2.367 +            } catch (Exception ex) {
   2.368 +                throw new RuntimeException(ex);
   2.369 +            }
   2.370 +
   2.371 +            Class fieldt = field.getType();
   2.372 +            if (fieldt != long.class)
   2.373 +                throw new IllegalArgumentException("Must be long type");
   2.374 +
   2.375 +            if (!Modifier.isVolatile(modifiers))
   2.376 +                throw new IllegalArgumentException("Must be volatile type");
   2.377 +
   2.378 +            this.cclass = (Modifier.isProtected(modifiers) &&
   2.379 +                           caller != tclass) ? caller : null;
   2.380 +            this.tclass = tclass;
   2.381 +            offset = unsafe.objectFieldOffset(field);
   2.382 +        }
   2.383 +
   2.384 +        private void fullCheck(T obj) {
   2.385 +            if (!tclass.isInstance(obj))
   2.386 +                throw new ClassCastException();
   2.387 +            if (cclass != null)
   2.388 +                ensureProtectedAccess(obj);
   2.389 +        }
   2.390 +
   2.391 +        public boolean compareAndSet(T obj, long expect, long update) {
   2.392 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.393 +            synchronized (this) {
   2.394 +                long v = unsafe.getLong(obj, offset);
   2.395 +                if (v != expect)
   2.396 +                    return false;
   2.397 +                unsafe.putLong(obj, offset, update);
   2.398 +                return true;
   2.399 +            }
   2.400 +        }
   2.401 +
   2.402 +        public boolean weakCompareAndSet(T obj, long expect, long update) {
   2.403 +            return compareAndSet(obj, expect, update);
   2.404 +        }
   2.405 +
   2.406 +        public void set(T obj, long newValue) {
   2.407 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.408 +            synchronized (this) {
   2.409 +                unsafe.putLong(obj, offset, newValue);
   2.410 +            }
   2.411 +        }
   2.412 +
   2.413 +        public void lazySet(T obj, long newValue) {
   2.414 +            set(obj, newValue);
   2.415 +        }
   2.416 +
   2.417 +        public long get(T obj) {
   2.418 +            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
   2.419 +            synchronized (this) {
   2.420 +                return unsafe.getLong(obj, offset);
   2.421 +            }
   2.422 +        }
   2.423 +
   2.424 +        private void ensureProtectedAccess(T obj) {
   2.425 +            if (cclass.isInstance(obj)) {
   2.426 +                return;
   2.427 +            }
   2.428 +            throw new RuntimeException(
   2.429 +                new IllegalAccessException("Class " +
   2.430 +                    cclass.getName() +
   2.431 +                    " can not access a protected member of class " +
   2.432 +                    tclass.getName() +
   2.433 +                    " using an instance of " +
   2.434 +                    obj.getClass().getName()
   2.435 +                )
   2.436 +            );
   2.437 +        }
   2.438 +    }
   2.439 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Mon Feb 09 20:32:36 2015 +0100
     3.3 @@ -0,0 +1,304 @@
     3.4 +/*
     3.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.6 + *
     3.7 + * This code is free software; you can redistribute it and/or modify it
     3.8 + * under the terms of the GNU General Public License version 2 only, as
     3.9 + * published by the Free Software Foundation.  Oracle designates this
    3.10 + * particular file as subject to the "Classpath" exception as provided
    3.11 + * by Oracle in the LICENSE file that accompanied this code.
    3.12 + *
    3.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.16 + * version 2 for more details (a copy is included in the LICENSE file that
    3.17 + * accompanied this code).
    3.18 + *
    3.19 + * You should have received a copy of the GNU General Public License version
    3.20 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.22 + *
    3.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.24 + * or visit www.oracle.com if you need additional information or have any
    3.25 + * questions.
    3.26 + */
    3.27 +
    3.28 +/*
    3.29 + * This file is available under and governed by the GNU General Public
    3.30 + * License version 2 only, as published by the Free Software Foundation.
    3.31 + * However, the following notice accompanied the original version of this
    3.32 + * file:
    3.33 + *
    3.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
    3.35 + * Expert Group and released to the public domain, as explained at
    3.36 + * http://creativecommons.org/publicdomain/zero/1.0/
    3.37 + */
    3.38 +
    3.39 +package java.util.concurrent.atomic;
    3.40 +import sun.misc.Unsafe;
    3.41 +import java.lang.reflect.*;
    3.42 +
    3.43 +/**
    3.44 + * A reflection-based utility that enables atomic updates to
    3.45 + * designated {@code volatile} reference fields of designated
    3.46 + * classes.  This class is designed for use in atomic data structures
    3.47 + * in which several reference fields of the same node are
    3.48 + * independently subject to atomic updates. For example, a tree node
    3.49 + * might be declared as
    3.50 + *
    3.51 + *  <pre> {@code
    3.52 + * class Node {
    3.53 + *   private volatile Node left, right;
    3.54 + *
    3.55 + *   private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
    3.56 + *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
    3.57 + *   private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
    3.58 + *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
    3.59 + *
    3.60 + *   Node getLeft() { return left;  }
    3.61 + *   boolean compareAndSetLeft(Node expect, Node update) {
    3.62 + *     return leftUpdater.compareAndSet(this, expect, update);
    3.63 + *   }
    3.64 + *   // ... and so on
    3.65 + * }}</pre>
    3.66 + *
    3.67 + * <p>Note that the guarantees of the {@code compareAndSet}
    3.68 + * method in this class are weaker than in other atomic classes.
    3.69 + * Because this class cannot ensure that all uses of the field
    3.70 + * are appropriate for purposes of atomic access, it can
    3.71 + * guarantee atomicity only with respect to other invocations of
    3.72 + * {@code compareAndSet} and {@code set} on the same updater.
    3.73 + *
    3.74 + * @since 1.5
    3.75 + * @author Doug Lea
    3.76 + * @param <T> The type of the object holding the updatable field
    3.77 + * @param <V> The type of the field
    3.78 + */
    3.79 +public abstract class AtomicReferenceFieldUpdater<T, V> {
    3.80 +
    3.81 +    /**
    3.82 +     * Creates and returns an updater for objects with the given field.
    3.83 +     * The Class arguments are needed to check that reflective types and
    3.84 +     * generic types match.
    3.85 +     *
    3.86 +     * @param tclass the class of the objects holding the field.
    3.87 +     * @param vclass the class of the field
    3.88 +     * @param fieldName the name of the field to be updated.
    3.89 +     * @return the updater
    3.90 +     * @throws IllegalArgumentException if the field is not a volatile reference type.
    3.91 +     * @throws RuntimeException with a nested reflection-based
    3.92 +     * exception if the class does not hold field or is the wrong type.
    3.93 +     */
    3.94 +    public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
    3.95 +        return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
    3.96 +                                                        vclass,
    3.97 +                                                        fieldName);
    3.98 +    }
    3.99 +
   3.100 +    /**
   3.101 +     * Protected do-nothing constructor for use by subclasses.
   3.102 +     */
   3.103 +    protected AtomicReferenceFieldUpdater() {
   3.104 +    }
   3.105 +
   3.106 +    /**
   3.107 +     * Atomically sets the field of the given object managed by this updater
   3.108 +     * to the given updated value if the current value {@code ==} the
   3.109 +     * expected value. This method is guaranteed to be atomic with respect to
   3.110 +     * other calls to {@code compareAndSet} and {@code set}, but not
   3.111 +     * necessarily with respect to other changes in the field.
   3.112 +     *
   3.113 +     * @param obj An object whose field to conditionally set
   3.114 +     * @param expect the expected value
   3.115 +     * @param update the new value
   3.116 +     * @return true if successful.
   3.117 +     */
   3.118 +    public abstract boolean compareAndSet(T obj, V expect, V update);
   3.119 +
   3.120 +    /**
   3.121 +     * Atomically sets the field of the given object managed by this updater
   3.122 +     * to the given updated value if the current value {@code ==} the
   3.123 +     * expected value. This method is guaranteed to be atomic with respect to
   3.124 +     * other calls to {@code compareAndSet} and {@code set}, but not
   3.125 +     * necessarily with respect to other changes in the field.
   3.126 +     *
   3.127 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
   3.128 +     * and does not provide ordering guarantees, so is only rarely an
   3.129 +     * appropriate alternative to {@code compareAndSet}.
   3.130 +     *
   3.131 +     * @param obj An object whose field to conditionally set
   3.132 +     * @param expect the expected value
   3.133 +     * @param update the new value
   3.134 +     * @return true if successful.
   3.135 +     */
   3.136 +    public abstract boolean weakCompareAndSet(T obj, V expect, V update);
   3.137 +
   3.138 +    /**
   3.139 +     * Sets the field of the given object managed by this updater to the
   3.140 +     * given updated value. This operation is guaranteed to act as a volatile
   3.141 +     * store with respect to subsequent invocations of {@code compareAndSet}.
   3.142 +     *
   3.143 +     * @param obj An object whose field to set
   3.144 +     * @param newValue the new value
   3.145 +     */
   3.146 +    public abstract void set(T obj, V newValue);
   3.147 +
   3.148 +    /**
   3.149 +     * Eventually sets the field of the given object managed by this
   3.150 +     * updater to the given updated value.
   3.151 +     *
   3.152 +     * @param obj An object whose field to set
   3.153 +     * @param newValue the new value
   3.154 +     * @since 1.6
   3.155 +     */
   3.156 +    public abstract void lazySet(T obj, V newValue);
   3.157 +
   3.158 +    /**
   3.159 +     * Gets the current value held in the field of the given object managed
   3.160 +     * by this updater.
   3.161 +     *
   3.162 +     * @param obj An object whose field to get
   3.163 +     * @return the current value
   3.164 +     */
   3.165 +    public abstract V get(T obj);
   3.166 +
   3.167 +    /**
   3.168 +     * Atomically sets the field of the given object managed by this updater
   3.169 +     * to the given value and returns the old value.
   3.170 +     *
   3.171 +     * @param obj An object whose field to get and set
   3.172 +     * @param newValue the new value
   3.173 +     * @return the previous value
   3.174 +     */
   3.175 +    public V getAndSet(T obj, V newValue) {
   3.176 +        for (;;) {
   3.177 +            V current = get(obj);
   3.178 +            if (compareAndSet(obj, current, newValue))
   3.179 +                return current;
   3.180 +        }
   3.181 +    }
   3.182 +
   3.183 +    private static final class AtomicReferenceFieldUpdaterImpl<T,V>
   3.184 +        extends AtomicReferenceFieldUpdater<T,V> {
   3.185 +        private static final Unsafe unsafe = Unsafe.getUnsafe();
   3.186 +        private final long offset;
   3.187 +        private final Class<T> tclass;
   3.188 +        private final Class<V> vclass;
   3.189 +        private final Class cclass;
   3.190 +
   3.191 +        /*
   3.192 +         * Internal type checks within all update methods contain
   3.193 +         * internal inlined optimizations checking for the common
   3.194 +         * cases where the class is final (in which case a simple
   3.195 +         * getClass comparison suffices) or is of type Object (in
   3.196 +         * which case no check is needed because all objects are
   3.197 +         * instances of Object). The Object case is handled simply by
   3.198 +         * setting vclass to null in constructor.  The targetCheck and
   3.199 +         * updateCheck methods are invoked when these faster
   3.200 +         * screenings fail.
   3.201 +         */
   3.202 +
   3.203 +        AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
   3.204 +                                        Class<V> vclass,
   3.205 +                                        String fieldName) {
   3.206 +            Field field = null;
   3.207 +            Class fieldClass = null;
   3.208 +            Class caller = null;
   3.209 +            int modifiers = 0;
   3.210 +            try {
   3.211 +                field = tclass.getDeclaredField(fieldName);
   3.212 +                caller = sun.reflect.Reflection.getCallerClass(3);
   3.213 +                modifiers = field.getModifiers();
   3.214 +                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
   3.215 +                    caller, tclass, null, modifiers);
   3.216 +                sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
   3.217 +                fieldClass = field.getType();
   3.218 +            } catch (Exception ex) {
   3.219 +                throw new RuntimeException(ex);
   3.220 +            }
   3.221 +
   3.222 +            if (vclass != fieldClass)
   3.223 +                throw new ClassCastException();
   3.224 +
   3.225 +            if (!Modifier.isVolatile(modifiers))
   3.226 +                throw new IllegalArgumentException("Must be volatile type");
   3.227 +
   3.228 +            this.cclass = (Modifier.isProtected(modifiers) &&
   3.229 +                           caller != tclass) ? caller : null;
   3.230 +            this.tclass = tclass;
   3.231 +            if (vclass == Object.class)
   3.232 +                this.vclass = null;
   3.233 +            else
   3.234 +                this.vclass = vclass;
   3.235 +            offset = unsafe.objectFieldOffset(field);
   3.236 +        }
   3.237 +
   3.238 +        void targetCheck(T obj) {
   3.239 +            if (!tclass.isInstance(obj))
   3.240 +                throw new ClassCastException();
   3.241 +            if (cclass != null)
   3.242 +                ensureProtectedAccess(obj);
   3.243 +        }
   3.244 +
   3.245 +        void updateCheck(T obj, V update) {
   3.246 +            if (!tclass.isInstance(obj) ||
   3.247 +                (update != null && vclass != null && !vclass.isInstance(update)))
   3.248 +                throw new ClassCastException();
   3.249 +            if (cclass != null)
   3.250 +                ensureProtectedAccess(obj);
   3.251 +        }
   3.252 +
   3.253 +        public boolean compareAndSet(T obj, V expect, V update) {
   3.254 +            if (obj == null || obj.getClass() != tclass || cclass != null ||
   3.255 +                (update != null && vclass != null &&
   3.256 +                 vclass != update.getClass()))
   3.257 +                updateCheck(obj, update);
   3.258 +            return unsafe.compareAndSwapObject(obj, offset, expect, update);
   3.259 +        }
   3.260 +
   3.261 +        public boolean weakCompareAndSet(T obj, V expect, V update) {
   3.262 +            // same implementation as strong form for now
   3.263 +            if (obj == null || obj.getClass() != tclass || cclass != null ||
   3.264 +                (update != null && vclass != null &&
   3.265 +                 vclass != update.getClass()))
   3.266 +                updateCheck(obj, update);
   3.267 +            return unsafe.compareAndSwapObject(obj, offset, expect, update);
   3.268 +        }
   3.269 +
   3.270 +        public void set(T obj, V newValue) {
   3.271 +            if (obj == null || obj.getClass() != tclass || cclass != null ||
   3.272 +                (newValue != null && vclass != null &&
   3.273 +                 vclass != newValue.getClass()))
   3.274 +                updateCheck(obj, newValue);
   3.275 +            unsafe.putObjectVolatile(obj, offset, newValue);
   3.276 +        }
   3.277 +
   3.278 +        public void lazySet(T obj, V newValue) {
   3.279 +            if (obj == null || obj.getClass() != tclass || cclass != null ||
   3.280 +                (newValue != null && vclass != null &&
   3.281 +                 vclass != newValue.getClass()))
   3.282 +                updateCheck(obj, newValue);
   3.283 +            unsafe.putOrderedObject(obj, offset, newValue);
   3.284 +        }
   3.285 +
   3.286 +        public V get(T obj) {
   3.287 +            if (obj == null || obj.getClass() != tclass || cclass != null)
   3.288 +                targetCheck(obj);
   3.289 +            return (V)unsafe.getObjectVolatile(obj, offset);
   3.290 +        }
   3.291 +
   3.292 +        private void ensureProtectedAccess(T obj) {
   3.293 +            if (cclass.isInstance(obj)) {
   3.294 +                return;
   3.295 +            }
   3.296 +            throw new RuntimeException(
   3.297 +                new IllegalAccessException("Class " +
   3.298 +                    cclass.getName() +
   3.299 +                    " can not access a protected member of class " +
   3.300 +                    tclass.getName() +
   3.301 +                    " using an instance of " +
   3.302 +                    obj.getClass().getName()
   3.303 +                )
   3.304 +            );
   3.305 +        }
   3.306 +    }
   3.307 +}