1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Written by Doug Lea with assistance from members of JCP JSR-166
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Expert Group and released to the public domain, as explained at
4a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * http://creativecommons.org/publicdomain/zero/1.0/
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util.concurrent.atomic;
8a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilsonimport dalvik.system.VMStack; // android-added
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport sun.misc.Unsafe;
1091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravleimport java.lang.reflect.Field;
1191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravleimport java.lang.reflect.Modifier;
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A reflection-based utility that enables atomic updates to
15bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * designated {@code volatile} reference fields of designated
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * classes.  This class is designed for use in atomic data structures
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * in which several reference fields of the same node are
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * independently subject to atomic updates. For example, a tree node
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * might be declared as
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
218eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson *  <pre> {@code
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * class Node {
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   private volatile Node left, right;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
258eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson *   private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
278eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson *   private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   Node getLeft() { return left;  }
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   boolean compareAndSetLeft(Node expect, Node update) {
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     return leftUpdater.compareAndSet(this, expect, update);
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   // ... and so on
358eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson * }}</pre>
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
37bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * <p>Note that the guarantees of the {@code compareAndSet}
38bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * method in this class are weaker than in other atomic classes.
39bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * Because this class cannot ensure that all uses of the field
40bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * are appropriate for purposes of atomic access, it can
41bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * guarantee atomicity only with respect to other invocations of
42bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson * {@code compareAndSet} and {@code set} on the same updater.
43bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson *
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @since 1.5
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Doug Lea
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param <T> The type of the object holding the updatable field
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param <V> The type of the field
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
4991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravlepublic abstract class AtomicReferenceFieldUpdater<T,V> {
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
52bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Creates and returns an updater for objects with the given field.
53bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * The Class arguments are needed to check that reflective types and
54bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * generic types match.
55bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
5691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * @param tclass the class of the objects holding the field
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param vclass the class of the field
5891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * @param fieldName the name of the field to be updated
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the updater
6091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * @throws IllegalArgumentException if the field is not a volatile reference type
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws RuntimeException with a nested reflection-based
6291770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * exception if the class does not hold field or is the wrong type,
6391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * or the field is inaccessible to the caller according to Java language
6491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * access control
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
67bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
68bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                                                        vclass,
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                        fieldName);
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Protected do-nothing constructor for use by subclasses.
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected AtomicReferenceFieldUpdater() {
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
79bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Atomically sets the field of the given object managed by this updater
80bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * to the given updated value if the current value {@code ==} the
81bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * expected value. This method is guaranteed to be atomic with respect to
82bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * other calls to {@code compareAndSet} and {@code set}, but not
83bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * necessarily with respect to other changes in the field.
84bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj An object whose field to conditionally set
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expect the expected value
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param update the new value
8891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * @return true if successful
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public abstract boolean compareAndSet(T obj, V expect, V update);
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
93bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Atomically sets the field of the given object managed by this updater
94bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * to the given updated value if the current value {@code ==} the
95bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * expected value. This method is guaranteed to be atomic with respect to
96bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * other calls to {@code compareAndSet} and {@code set}, but not
97bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * necessarily with respect to other changes in the field.
98bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
9991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * <p><a href="package-summary.html#weakCompareAndSet">May fail
10091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * spuriously and does not provide ordering guarantees</a>, so is
10191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * only rarely an appropriate alternative to {@code compareAndSet}.
102bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj An object whose field to conditionally set
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expect the expected value
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param update the new value
10691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * @return true if successful
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public abstract boolean weakCompareAndSet(T obj, V expect, V update);
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
111bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Sets the field of the given object managed by this updater to the
112bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * given updated value. This operation is guaranteed to act as a volatile
113bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * store with respect to subsequent invocations of {@code compareAndSet}.
114bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj An object whose field to set
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newValue the new value
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public abstract void set(T obj, V newValue);
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1216232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * Eventually sets the field of the given object managed by this
1226232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * updater to the given updated value.
1236232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     *
1246232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * @param obj An object whose field to set
1256232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * @param newValue the new value
1266232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * @since 1.6
1276232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     */
1286232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    public abstract void lazySet(T obj, V newValue);
1296232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
1306232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    /**
131bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Gets the current value held in the field of the given object managed
132bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * by this updater.
133bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj An object whose field to get
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the current value
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public abstract V get(T obj);
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
140bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Atomically sets the field of the given object managed by this updater
141bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * to the given value and returns the old value.
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj An object whose field to get and set
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newValue the new value
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the previous value
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public V getAndSet(T obj, V newValue) {
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (;;) {
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            V current = get(obj);
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (compareAndSet(obj, current, newValue))
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return current;
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
155bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson    private static final class AtomicReferenceFieldUpdaterImpl<T,V>
156bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        extends AtomicReferenceFieldUpdater<T,V> {
1576232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        private static final Unsafe unsafe = Unsafe.getUnsafe();
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private final long offset;
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private final Class<T> tclass;
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        private final Class<V> vclass;
161a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        private final Class<?> cclass;
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
163bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        /*
164bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * Internal type checks within all update methods contain
165bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * internal inlined optimizations checking for the common
166bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * cases where the class is final (in which case a simple
167bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * getClass comparison suffices) or is of type Object (in
168bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * which case no check is needed because all objects are
169bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * instances of Object). The Object case is handled simply by
170bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * setting vclass to null in constructor.  The targetCheck and
171bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * updateCheck methods are invoked when these faster
172bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         * screenings fail.
173bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson         */
174bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
17591770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
176bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                                        Class<V> vclass,
17791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle                                        final String fieldName) {
17891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            final Field field;
17991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            final Class<?> fieldClass;
18091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            final Class<?> caller;
18191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            final int modifiers;
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
18391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle                field = tclass.getDeclaredField(fieldName); // android-changed
1846232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson                caller = VMStack.getStackClass2(); // android-changed
185bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                modifiers = field.getModifiers();
18691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            // BEGIN android-removed
18791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //     sun.reflect.misc.ReflectUtil.ensureMemberAccess(
18891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //         caller, tclass, null, modifiers);
18991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //     ClassLoader cl = tclass.getClassLoader();
19091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //     ClassLoader ccl = caller.getClassLoader();
19191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //     if ((ccl != null) && (ccl != cl) &&
19291770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //         ((cl == null) || !isAncestor(cl, ccl))) {
19391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //       sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
19491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //     }
19591770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            // END android-removed
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fieldClass = field.getType();
19791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            // BEGIN android-removed
19891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            // } catch (PrivilegedActionException pae) {
19991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            //     throw new RuntimeException(pae.getException());
20091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            // END android-removed
201bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            } catch (Exception ex) {
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new RuntimeException(ex);
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
204bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (vclass != fieldClass)
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new ClassCastException();
207bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
208bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (!Modifier.isVolatile(modifiers))
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalArgumentException("Must be volatile type");
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
211bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            this.cclass = (Modifier.isProtected(modifiers) &&
212bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                           caller != tclass) ? caller : null;
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.tclass = tclass;
214bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (vclass == Object.class)
215bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                this.vclass = null;
216bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            else
217bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                this.vclass = vclass;
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            offset = unsafe.objectFieldOffset(field);
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
22191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        // BEGIN android-removed
22291770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        // /**
22391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //  * Returns true if the second classloader can be found in the first
22491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //  * classloader's delegation chain.
22591770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //  * Equivalent to the inaccessible: first.isAncestor(second).
22691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //  */
22791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //
22891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
22991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //     ClassLoader acl = first;
23091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //     do {
23191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //         acl = acl.getParent();
23291770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //         if (second == acl) {
23391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //             return true;
23491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //        }
23591770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //     } while (acl != null);
23691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        //     return false;
23791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        // }
23891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        // END android-removed
23991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle
240bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        void targetCheck(T obj) {
241bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (!tclass.isInstance(obj))
242bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                throw new ClassCastException();
243bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (cclass != null)
244bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                ensureProtectedAccess(obj);
245bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        }
246bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
247bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        void updateCheck(T obj, V update) {
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!tclass.isInstance(obj) ||
249bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                (update != null && vclass != null && !vclass.isInstance(update)))
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new ClassCastException();
251bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (cclass != null)
252bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                ensureProtectedAccess(obj);
253bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        }
254bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
255bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        public boolean compareAndSet(T obj, V expect, V update) {
256bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (obj == null || obj.getClass() != tclass || cclass != null ||
257bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                (update != null && vclass != null &&
258bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                 vclass != update.getClass()))
259bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                updateCheck(obj, update);
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return unsafe.compareAndSwapObject(obj, offset, expect, update);
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public boolean weakCompareAndSet(T obj, V expect, V update) {
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // same implementation as strong form for now
265bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (obj == null || obj.getClass() != tclass || cclass != null ||
266bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                (update != null && vclass != null &&
267bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                 vclass != update.getClass()))
268bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                updateCheck(obj, update);
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return unsafe.compareAndSwapObject(obj, offset, expect, update);
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void set(T obj, V newValue) {
273bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (obj == null || obj.getClass() != tclass || cclass != null ||
274bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                (newValue != null && vclass != null &&
275bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                 vclass != newValue.getClass()))
276bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                updateCheck(obj, newValue);
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            unsafe.putObjectVolatile(obj, offset, newValue);
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2806232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        public void lazySet(T obj, V newValue) {
2816232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson            if (obj == null || obj.getClass() != tclass || cclass != null ||
2826232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson                (newValue != null && vclass != null &&
2836232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson                 vclass != newValue.getClass()))
2846232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson                updateCheck(obj, newValue);
2856232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson            unsafe.putOrderedObject(obj, offset, newValue);
2866232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        }
2876232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
28891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        @SuppressWarnings("unchecked")
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public V get(T obj) {
290bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (obj == null || obj.getClass() != tclass || cclass != null)
291bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                targetCheck(obj);
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return (V)unsafe.getObjectVolatile(obj, offset);
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
294bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
295bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        private void ensureProtectedAccess(T obj) {
296bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            if (cclass.isInstance(obj)) {
297bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                return;
298bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            }
2998eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson            throw new RuntimeException(
300bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                new IllegalAccessException("Class " +
301bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                    cclass.getName() +
302bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                    " can not access a protected member of class " +
303bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                    tclass.getName() +
304bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                    " using an instance of " +
305bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                    obj.getClass().getName()
306bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson                )
307bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson            );
308bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson        }
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
311