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