AtomicIntegerFieldUpdater.java revision 14176:8606d027b2c2
11573Srgrimes/*
21573Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31573Srgrimes *
41573Srgrimes * This code is free software; you can redistribute it and/or modify it
51573Srgrimes * under the terms of the GNU General Public License version 2 only, as
61573Srgrimes * published by the Free Software Foundation.  Oracle designates this
71573Srgrimes * particular file as subject to the "Classpath" exception as provided
81573Srgrimes * by Oracle in the LICENSE file that accompanied this code.
91573Srgrimes *
101573Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
111573Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
121573Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
131573Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
141573Srgrimes * accompanied this code).
151573Srgrimes *
16148834Sstefanf * You should have received a copy of the GNU General Public License version
171573Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
181573Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
191573Srgrimes *
201573Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
211573Srgrimes * or visit www.oracle.com if you need additional information or have any
221573Srgrimes * questions.
231573Srgrimes */
241573Srgrimes
251573Srgrimes/*
261573Srgrimes * This file is available under and governed by the GNU General Public
271573Srgrimes * License version 2 only, as published by the Free Software Foundation.
281573Srgrimes * However, the following notice accompanied the original version of this
291573Srgrimes * file:
301573Srgrimes *
311573Srgrimes * Written by Doug Lea with assistance from members of JCP JSR-166
321573Srgrimes * Expert Group and released to the public domain, as explained at
33148834Sstefanf * http://creativecommons.org/publicdomain/zero/1.0/
3484260Sobrien */
351573Srgrimes
361573Srgrimespackage java.util.concurrent.atomic;
371573Srgrimes
381573Srgrimesimport java.lang.reflect.Field;
391573Srgrimesimport java.lang.reflect.Modifier;
401573Srgrimesimport java.security.AccessController;
4184260Sobrienimport java.security.PrivilegedActionException;
421573Srgrimesimport java.security.PrivilegedExceptionAction;
431573Srgrimesimport java.util.function.IntBinaryOperator;
441573Srgrimesimport java.util.function.IntUnaryOperator;
4584260Sobrienimport jdk.internal.reflect.CallerSensitive;
461573Srgrimesimport jdk.internal.reflect.Reflection;
471573Srgrimes
4884260Sobrien/**
4984260Sobrien * A reflection-based utility that enables atomic updates to
5084260Sobrien * designated {@code volatile int} fields of designated classes.
5184260Sobrien * This class is designed for use in atomic data structures in which
5284260Sobrien * several fields of the same node are independently subject to atomic
5384260Sobrien * updates.
5484260Sobrien *
551573Srgrimes * <p>Note that the guarantees of the {@code compareAndSet}
561573Srgrimes * method in this class are weaker than in other atomic classes.
5784260Sobrien * Because this class cannot ensure that all uses of the field
5884260Sobrien * are appropriate for purposes of atomic access, it can
5984260Sobrien * guarantee atomicity only with respect to other invocations of
601573Srgrimes * {@code compareAndSet} and {@code set} on the same updater.
611573Srgrimes *
621573Srgrimes * @since 1.5
631573Srgrimes * @author Doug Lea
641573Srgrimes * @param <T> The type of the object holding the updatable field
65148834Sstefanf */
6684260Sobrienpublic abstract class AtomicIntegerFieldUpdater<T> {
6784260Sobrien    /**
681573Srgrimes     * Creates and returns an updater for objects with the given field.
6984260Sobrien     * The Class argument is needed to check that reflective types and
7084260Sobrien     * generic types match.
7184260Sobrien     *
7284260Sobrien     * @param tclass the class of the objects holding the field
73148834Sstefanf     * @param fieldName the name of the field to be updated
7484260Sobrien     * @param <U> the type of instances of tclass
751573Srgrimes     * @return the updater
761573Srgrimes     * @throws IllegalArgumentException if the field is not a
77     * volatile integer type
78     * @throws RuntimeException with a nested reflection-based
79     * exception if the class does not hold field or is the wrong type,
80     * or the field is inaccessible to the caller according to Java language
81     * access control
82     */
83    @CallerSensitive
84    public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
85                                                              String fieldName) {
86        return new AtomicIntegerFieldUpdaterImpl<U>
87            (tclass, fieldName, Reflection.getCallerClass());
88    }
89
90    /**
91     * Protected do-nothing constructor for use by subclasses.
92     */
93    protected AtomicIntegerFieldUpdater() {
94    }
95
96    /**
97     * Atomically sets the field of the given object managed by this updater
98     * to the given updated value if the current value {@code ==} the
99     * expected value. This method is guaranteed to be atomic with respect to
100     * other calls to {@code compareAndSet} and {@code set}, but not
101     * necessarily with respect to other changes in the field.
102     *
103     * @param obj An object whose field to conditionally set
104     * @param expect the expected value
105     * @param update the new value
106     * @return {@code true} if successful
107     * @throws ClassCastException if {@code obj} is not an instance
108     * of the class possessing the field established in the constructor
109     */
110    public abstract boolean compareAndSet(T obj, int expect, int update);
111
112    /**
113     * Atomically sets the field of the given object managed by this updater
114     * to the given updated value if the current value {@code ==} the
115     * expected value. This method is guaranteed to be atomic with respect to
116     * other calls to {@code compareAndSet} and {@code set}, but not
117     * necessarily with respect to other changes in the field.
118     *
119     * <p><a href="package-summary.html#weakCompareAndSet">May fail
120     * spuriously and does not provide ordering guarantees</a>, so is
121     * only rarely an appropriate alternative to {@code compareAndSet}.
122     *
123     * @param obj An object whose field to conditionally set
124     * @param expect the expected value
125     * @param update the new value
126     * @return {@code true} if successful
127     * @throws ClassCastException if {@code obj} is not an instance
128     * of the class possessing the field established in the constructor
129     */
130    public abstract boolean weakCompareAndSet(T obj, int expect, int update);
131
132    /**
133     * Sets the field of the given object managed by this updater to the
134     * given updated value. This operation is guaranteed to act as a volatile
135     * store with respect to subsequent invocations of {@code compareAndSet}.
136     *
137     * @param obj An object whose field to set
138     * @param newValue the new value
139     */
140    public abstract void set(T obj, int newValue);
141
142    /**
143     * Eventually sets the field of the given object managed by this
144     * updater to the given updated value.
145     *
146     * @param obj An object whose field to set
147     * @param newValue the new value
148     * @since 1.6
149     */
150    public abstract void lazySet(T obj, int newValue);
151
152    /**
153     * Gets the current value held in the field of the given object managed
154     * by this updater.
155     *
156     * @param obj An object whose field to get
157     * @return the current value
158     */
159    public abstract int get(T obj);
160
161    /**
162     * Atomically sets the field of the given object managed by this updater
163     * to the given value and returns the old value.
164     *
165     * @param obj An object whose field to get and set
166     * @param newValue the new value
167     * @return the previous value
168     */
169    public int getAndSet(T obj, int newValue) {
170        int prev;
171        do {
172            prev = get(obj);
173        } while (!compareAndSet(obj, prev, newValue));
174        return prev;
175    }
176
177    /**
178     * Atomically increments by one the current value of the field of the
179     * given object managed by this updater.
180     *
181     * @param obj An object whose field to get and set
182     * @return the previous value
183     */
184    public int getAndIncrement(T obj) {
185        int prev, next;
186        do {
187            prev = get(obj);
188            next = prev + 1;
189        } while (!compareAndSet(obj, prev, next));
190        return prev;
191    }
192
193    /**
194     * Atomically decrements by one the current value of the field of the
195     * given object managed by this updater.
196     *
197     * @param obj An object whose field to get and set
198     * @return the previous value
199     */
200    public int getAndDecrement(T obj) {
201        int prev, next;
202        do {
203            prev = get(obj);
204            next = prev - 1;
205        } while (!compareAndSet(obj, prev, next));
206        return prev;
207    }
208
209    /**
210     * Atomically adds the given value to the current value of the field of
211     * the given object managed by this updater.
212     *
213     * @param obj An object whose field to get and set
214     * @param delta the value to add
215     * @return the previous value
216     */
217    public int getAndAdd(T obj, int delta) {
218        int prev, next;
219        do {
220            prev = get(obj);
221            next = prev + delta;
222        } while (!compareAndSet(obj, prev, next));
223        return prev;
224    }
225
226    /**
227     * Atomically increments by one the current value of the field of the
228     * given object managed by this updater.
229     *
230     * @param obj An object whose field to get and set
231     * @return the updated value
232     */
233    public int incrementAndGet(T obj) {
234        int prev, next;
235        do {
236            prev = get(obj);
237            next = prev + 1;
238        } while (!compareAndSet(obj, prev, next));
239        return next;
240    }
241
242    /**
243     * Atomically decrements by one the current value of the field of the
244     * given object managed by this updater.
245     *
246     * @param obj An object whose field to get and set
247     * @return the updated value
248     */
249    public int decrementAndGet(T obj) {
250        int prev, next;
251        do {
252            prev = get(obj);
253            next = prev - 1;
254        } while (!compareAndSet(obj, prev, next));
255        return next;
256    }
257
258    /**
259     * Atomically adds the given value to the current value of the field of
260     * the given object managed by this updater.
261     *
262     * @param obj An object whose field to get and set
263     * @param delta the value to add
264     * @return the updated value
265     */
266    public int addAndGet(T obj, int delta) {
267        int prev, next;
268        do {
269            prev = get(obj);
270            next = prev + delta;
271        } while (!compareAndSet(obj, prev, next));
272        return next;
273    }
274
275    /**
276     * Atomically updates the field of the given object managed by this updater
277     * with the results of applying the given function, returning the previous
278     * value. The function should be side-effect-free, since it may be
279     * re-applied when attempted updates fail due to contention among threads.
280     *
281     * @param obj An object whose field to get and set
282     * @param updateFunction a side-effect-free function
283     * @return the previous value
284     * @since 1.8
285     */
286    public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
287        int prev, next;
288        do {
289            prev = get(obj);
290            next = updateFunction.applyAsInt(prev);
291        } while (!compareAndSet(obj, prev, next));
292        return prev;
293    }
294
295    /**
296     * Atomically updates the field of the given object managed by this updater
297     * with the results of applying the given function, returning the updated
298     * value. The function should be side-effect-free, since it may be
299     * re-applied when attempted updates fail due to contention among threads.
300     *
301     * @param obj An object whose field to get and set
302     * @param updateFunction a side-effect-free function
303     * @return the updated value
304     * @since 1.8
305     */
306    public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
307        int prev, next;
308        do {
309            prev = get(obj);
310            next = updateFunction.applyAsInt(prev);
311        } while (!compareAndSet(obj, prev, next));
312        return next;
313    }
314
315    /**
316     * Atomically updates the field of the given object managed by this
317     * updater with the results of applying the given function to the
318     * current and given values, returning the previous value. The
319     * function should be side-effect-free, since it may be re-applied
320     * when attempted updates fail due to contention among threads.  The
321     * function is applied with the current value as its first argument,
322     * and the given update as the second argument.
323     *
324     * @param obj An object whose field to get and set
325     * @param x the update value
326     * @param accumulatorFunction a side-effect-free function of two arguments
327     * @return the previous value
328     * @since 1.8
329     */
330    public final int getAndAccumulate(T obj, int x,
331                                      IntBinaryOperator accumulatorFunction) {
332        int prev, next;
333        do {
334            prev = get(obj);
335            next = accumulatorFunction.applyAsInt(prev, x);
336        } while (!compareAndSet(obj, prev, next));
337        return prev;
338    }
339
340    /**
341     * Atomically updates the field of the given object managed by this
342     * updater with the results of applying the given function to the
343     * current and given values, returning the updated value. The
344     * function should be side-effect-free, since it may be re-applied
345     * when attempted updates fail due to contention among threads.  The
346     * function is applied with the current value as its first argument,
347     * and the given update as the second argument.
348     *
349     * @param obj An object whose field to get and set
350     * @param x the update value
351     * @param accumulatorFunction a side-effect-free function of two arguments
352     * @return the updated value
353     * @since 1.8
354     */
355    public final int accumulateAndGet(T obj, int x,
356                                      IntBinaryOperator accumulatorFunction) {
357        int prev, next;
358        do {
359            prev = get(obj);
360            next = accumulatorFunction.applyAsInt(prev, x);
361        } while (!compareAndSet(obj, prev, next));
362        return next;
363    }
364
365    /**
366     * Standard hotspot implementation using intrinsics.
367     */
368    private static final class AtomicIntegerFieldUpdaterImpl<T>
369        extends AtomicIntegerFieldUpdater<T> {
370        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
371        private final long offset;
372        /**
373         * if field is protected, the subclass constructing updater, else
374         * the same as tclass
375         */
376        private final Class<?> cclass;
377        /** class holding the field */
378        private final Class<T> tclass;
379
380        AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
381                                      final String fieldName,
382                                      final Class<?> caller) {
383            final Field field;
384            final int modifiers;
385            try {
386                field = AccessController.doPrivileged(
387                    new PrivilegedExceptionAction<Field>() {
388                        public Field run() throws NoSuchFieldException {
389                            return tclass.getDeclaredField(fieldName);
390                        }
391                    });
392                modifiers = field.getModifiers();
393                sun.reflect.misc.ReflectUtil.ensureMemberAccess(
394                    caller, tclass, null, modifiers);
395                ClassLoader cl = tclass.getClassLoader();
396                ClassLoader ccl = caller.getClassLoader();
397                if ((ccl != null) && (ccl != cl) &&
398                    ((cl == null) || !isAncestor(cl, ccl))) {
399                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
400                }
401            } catch (PrivilegedActionException pae) {
402                throw new RuntimeException(pae.getException());
403            } catch (Exception ex) {
404                throw new RuntimeException(ex);
405            }
406
407            if (field.getType() != int.class)
408                throw new IllegalArgumentException("Must be integer type");
409
410            if (!Modifier.isVolatile(modifiers))
411                throw new IllegalArgumentException("Must be volatile type");
412
413            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
414            this.tclass = tclass;
415            this.offset = U.objectFieldOffset(field);
416        }
417
418        /**
419         * Returns true if the second classloader can be found in the first
420         * classloader's delegation chain.
421         * Equivalent to the inaccessible: first.isAncestor(second).
422         */
423        private static boolean isAncestor(ClassLoader first, ClassLoader second) {
424            ClassLoader acl = first;
425            do {
426                acl = acl.getParent();
427                if (second == acl) {
428                    return true;
429                }
430            } while (acl != null);
431            return false;
432        }
433
434        /**
435         * Checks that target argument is instance of cclass.  On
436         * failure, throws cause.
437         */
438        private final void accessCheck(T obj) {
439            if (!cclass.isInstance(obj))
440                throwAccessCheckException(obj);
441        }
442
443        /**
444         * Throws access exception if accessCheck failed due to
445         * protected access, else ClassCastException.
446         */
447        private final void throwAccessCheckException(T obj) {
448            if (cclass == tclass)
449                throw new ClassCastException();
450            else
451                throw new RuntimeException(
452                    new IllegalAccessException(
453                        "Class " +
454                        cclass.getName() +
455                        " can not access a protected member of class " +
456                        tclass.getName() +
457                        " using an instance of " +
458                        obj.getClass().getName()));
459        }
460
461        public final boolean compareAndSet(T obj, int expect, int update) {
462            accessCheck(obj);
463            return U.compareAndSwapInt(obj, offset, expect, update);
464        }
465
466        public final boolean weakCompareAndSet(T obj, int expect, int update) {
467            accessCheck(obj);
468            return U.compareAndSwapInt(obj, offset, expect, update);
469        }
470
471        public final void set(T obj, int newValue) {
472            accessCheck(obj);
473            U.putIntVolatile(obj, offset, newValue);
474        }
475
476        public final void lazySet(T obj, int newValue) {
477            accessCheck(obj);
478            U.putIntRelease(obj, offset, newValue);
479        }
480
481        public final int get(T obj) {
482            accessCheck(obj);
483            return U.getIntVolatile(obj, offset);
484        }
485
486        public final int getAndSet(T obj, int newValue) {
487            accessCheck(obj);
488            return U.getAndSetInt(obj, offset, newValue);
489        }
490
491        public final int getAndAdd(T obj, int delta) {
492            accessCheck(obj);
493            return U.getAndAddInt(obj, offset, delta);
494        }
495
496        public final int getAndIncrement(T obj) {
497            return getAndAdd(obj, 1);
498        }
499
500        public final int getAndDecrement(T obj) {
501            return getAndAdd(obj, -1);
502        }
503
504        public final int incrementAndGet(T obj) {
505            return getAndAdd(obj, 1) + 1;
506        }
507
508        public final int decrementAndGet(T obj) {
509            return getAndAdd(obj, -1) - 1;
510        }
511
512        public final int addAndGet(T obj, int delta) {
513            return getAndAdd(obj, delta) + delta;
514        }
515
516    }
517}
518