# HG changeset patch # User dl # Date 1358338175 0 # Node ID c884f548a25f3574a3da9deb6ab95efe010d027c # Parent 379788c73130cf5fc20d6f77cd99879fee064154 8001666: Add lambda-compatible atomics and accumulators to the ActomicXXX classes Reviewed-by: dl, chegar, darcy, goetz Contributed-by: dl@cs.oswego.edu, chris.hegarty@oracle.com diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.IntUnaryOperator; +import java.util.function.IntBinaryOperator; import sun.misc.Unsafe; /** @@ -204,6 +206,92 @@ } /** + * Atomically updates the current value with the results of + * applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final int getAndUpdate(IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(); + next = updateFunction.operateAsInt(prev); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final int updateAndGet(IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(); + next = updateFunction.operateAsInt(prev); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the previous value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final int getAndAccumulate(int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(); + next = accumulatorFunction.operateAsInt(prev, x); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the updated value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final int accumulateAndGet(int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(); + next = accumulatorFunction.operateAsInt(prev, x); + } while (!compareAndSet(prev, next)); + return next; + } + + /** * Returns the String representation of the current value. * @return the String representation of the current value */ diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.IntUnaryOperator; +import java.util.function.IntBinaryOperator; import sun.misc.Unsafe; /** @@ -246,6 +248,100 @@ } /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final int getAndUpdate(int i, IntUnaryOperator updateFunction) { + long offset = checkedByteOffset(i); + int prev, next; + do { + prev = getRaw(offset); + next = updateFunction.operateAsInt(prev); + } while (!compareAndSetRaw(offset, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final int updateAndGet(int i, IntUnaryOperator updateFunction) { + long offset = checkedByteOffset(i); + int prev, next; + do { + prev = getRaw(offset); + next = updateFunction.operateAsInt(prev); + } while (!compareAndSetRaw(offset, prev, next)); + return next; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the previous value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final int getAndAccumulate(int i, int x, + IntBinaryOperator accumulatorFunction) { + long offset = checkedByteOffset(i); + int prev, next; + do { + prev = getRaw(offset); + next = accumulatorFunction.operateAsInt(prev, x); + } while (!compareAndSetRaw(offset, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the updated value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final int accumulateAndGet(int i, int x, + IntBinaryOperator accumulatorFunction) { + long offset = checkedByteOffset(i); + int prev, next; + do { + prev = getRaw(offset); + next = accumulatorFunction.operateAsInt(prev, x); + } while (!compareAndSetRaw(offset, prev, next)); + return next; + } + + /** * Returns the String representation of the current values of array. * @return the String representation of the current values of array */ diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.IntUnaryOperator; +import java.util.function.IntBinaryOperator; import sun.misc.Unsafe; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -265,6 +267,96 @@ } /** + * Atomically updates the field of the given object managed by this updater + * with the results of applying the given function, returning the previous + * value. The function should be side-effect-free, since it may be + * re-applied when attempted updates fail due to contention among threads. + * + * @param obj An object whose field to get and set + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(obj); + next = updateFunction.operateAsInt(prev); + } while (!compareAndSet(obj, prev, next)); + return prev; + } + + /** + * Atomically updates the field of the given object managed by this updater + * with the results of applying the given function, returning the updated + * value. The function should be side-effect-free, since it may be + * re-applied when attempted updates fail due to contention among threads. + * + * @param obj An object whose field to get and set + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final int updateAndGet(T obj, IntUnaryOperator updateFunction) { + int prev, next; + do { + prev = get(obj); + next = updateFunction.operateAsInt(prev); + } while (!compareAndSet(obj, prev, next)); + return next; + } + + /** + * Atomically updates the field of the given object managed by this + * updater with the results of applying the given function to the + * current and given values, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. The + * function is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param obj An object whose field to get and set + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final int getAndAccumulate(T obj, int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(obj); + next = accumulatorFunction.operateAsInt(prev, x); + } while (!compareAndSet(obj, prev, next)); + return prev; + } + + /** + * Atomically updates the field of the given object managed by this + * updater with the results of applying the given function to the + * current and given values, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. The + * function is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param obj An object whose field to get and set + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final int accumulateAndGet(T obj, int x, + IntBinaryOperator accumulatorFunction) { + int prev, next; + do { + prev = get(obj); + next = accumulatorFunction.operateAsInt(prev, x); + } while (!compareAndSet(obj, prev, next)); + return next; + } + + /** * Standard hotspot implementation using intrinsics */ private static class AtomicIntegerFieldUpdaterImpl extends AtomicIntegerFieldUpdater { diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.LongUnaryOperator; +import java.util.function.LongBinaryOperator; import sun.misc.Unsafe; /** @@ -218,6 +220,92 @@ } /** + * Atomically updates the current value with the results of + * applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final long getAndUpdate(LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(); + next = updateFunction.operateAsLong(prev); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final long updateAndGet(LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(); + next = updateFunction.operateAsLong(prev); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the previous value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final long getAndAccumulate(long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(); + next = accumulatorFunction.operateAsLong(prev, x); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the updated value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final long accumulateAndGet(long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(); + next = accumulatorFunction.operateAsLong(prev, x); + } while (!compareAndSet(prev, next)); + return next; + } + + /** * Returns the String representation of the current value. * @return the String representation of the current value */ diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.LongUnaryOperator; +import java.util.function.LongBinaryOperator; import sun.misc.Unsafe; /** @@ -245,6 +247,100 @@ } /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final long getAndUpdate(int i, LongUnaryOperator updateFunction) { + long offset = checkedByteOffset(i); + long prev, next; + do { + prev = getRaw(offset); + next = updateFunction.operateAsLong(prev); + } while (!compareAndSetRaw(offset, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final long updateAndGet(int i, LongUnaryOperator updateFunction) { + long offset = checkedByteOffset(i); + long prev, next; + do { + prev = getRaw(offset); + next = updateFunction.operateAsLong(prev); + } while (!compareAndSetRaw(offset, prev, next)); + return next; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the previous value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final long getAndAccumulate(int i, int x, + LongBinaryOperator accumulatorFunction) { + long offset = checkedByteOffset(i); + long prev, next; + do { + prev = getRaw(offset); + next = accumulatorFunction.operateAsLong(prev, x); + } while (!compareAndSetRaw(offset, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the updated value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final long accumulateAndGet(int i, int x, + LongBinaryOperator accumulatorFunction) { + long offset = checkedByteOffset(i); + long prev, next; + do { + prev = getRaw(offset); + next = accumulatorFunction.operateAsLong(prev, x); + } while (!compareAndSetRaw(offset, prev, next)); + return next; + } + + /** * Returns the String representation of the current values of array. * @return the String representation of the current values of array */ diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.LongUnaryOperator; +import java.util.function.LongBinaryOperator; import sun.misc.Unsafe; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -267,6 +269,96 @@ return next; } + /** + * Atomically updates the field of the given object managed by this updater + * with the results of applying the given function, returning the previous + * value. The function should be side-effect-free, since it may be + * re-applied when attempted updates fail due to contention among threads. + * + * @param obj An object whose field to get and set + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(obj); + next = updateFunction.operateAsLong(prev); + } while (!compareAndSet(obj, prev, next)); + return prev; + } + + /** + * Atomically updates the field of the given object managed by this updater + * with the results of applying the given function, returning the updated + * value. The function should be side-effect-free, since it may be + * re-applied when attempted updates fail due to contention among threads. + * + * @param obj An object whose field to get and set + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final long updateAndGet(T obj, LongUnaryOperator updateFunction) { + long prev, next; + do { + prev = get(obj); + next = updateFunction.operateAsLong(prev); + } while (!compareAndSet(obj, prev, next)); + return next; + } + + /** + * Atomically updates the field of the given object managed by this + * updater with the results of applying the given function to the + * current and given values, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. The + * function is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param obj An object whose field to get and set + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final long getAndAccumulate(T obj, long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(obj); + next = accumulatorFunction.operateAsLong(prev, x); + } while (!compareAndSet(obj, prev, next)); + return prev; + } + + /** + * Atomically updates the field of the given object managed by this + * updater with the results of applying the given function to the + * current and given values, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. The + * function is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param obj An object whose field to get and set + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final long accumulateAndGet(T obj, long x, + LongBinaryOperator accumulatorFunction) { + long prev, next; + do { + prev = get(obj); + next = accumulatorFunction.operateAsLong(prev, x); + } while (!compareAndSet(obj, prev, next)); + return next; + } + private static class CASUpdater extends AtomicLongFieldUpdater { private static final Unsafe unsafe = Unsafe.getUnsafe(); private final long offset; diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.UnaryOperator; +import java.util.function.BinaryOperator; import sun.misc.Unsafe; /** @@ -142,6 +144,92 @@ } /** + * Atomically updates the current value with the results of + * applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final V getAndUpdate(UnaryOperator updateFunction) { + V prev, next; + do { + prev = get(); + next = updateFunction.operate(prev); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final V updateAndGet(UnaryOperator updateFunction) { + V prev, next; + do { + prev = get(); + next = updateFunction.operate(prev); + } while (!compareAndSet(prev, next)); + return next; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the previous value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final V getAndAccumulate(V x, + BinaryOperator accumulatorFunction) { + V prev, next; + do { + prev = get(); + next = accumulatorFunction.operate(prev, x); + } while (!compareAndSet(prev, next)); + return prev; + } + + /** + * Atomically updates the current value with the results of + * applying the given function to the current and given values, + * returning the updated value. The function should be + * side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function + * is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final V accumulateAndGet(V x, + BinaryOperator accumulatorFunction) { + V prev, next; + do { + prev = get(); + next = accumulatorFunction.operate(prev, x); + } while (!compareAndSet(prev, next)); + return next; + } + + /** * Returns the String representation of the current value. * @return the String representation of the current value */ diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Wed Jan 16 12:09:35 2013 +0000 @@ -36,6 +36,8 @@ package java.util.concurrent.atomic; import java.util.Arrays; +import java.util.function.UnaryOperator; +import java.util.function.BinaryOperator; import java.lang.reflect.Array; import sun.misc.Unsafe; @@ -199,6 +201,100 @@ return compareAndSet(i, expect, update); } + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final E getAndUpdate(int i, UnaryOperator updateFunction) { + long offset = checkedByteOffset(i); + E prev, next; + do { + prev = getRaw(offset); + next = updateFunction.operate(prev); + } while (!compareAndSetRaw(offset, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the results + * of applying the given function, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. + * + * @param i the index + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final E updateAndGet(int i, UnaryOperator updateFunction) { + long offset = checkedByteOffset(i); + E prev, next; + do { + prev = getRaw(offset); + next = updateFunction.operate(prev); + } while (!compareAndSetRaw(offset, prev, next)); + return next; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the previous value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final E getAndAccumulate(int i, E x, + BinaryOperator accumulatorFunction) { + long offset = checkedByteOffset(i); + E prev, next; + do { + prev = getRaw(offset); + next = accumulatorFunction.operate(prev, x); + } while (!compareAndSetRaw(offset, prev, next)); + return prev; + } + + /** + * Atomically updates the element at index {@code i} with the + * results of applying the given function to the current and + * given values, returning the updated value. The function should + * be side-effect-free, since it may be re-applied when attempted + * updates fail due to contention among threads. The function is + * applied with the current value at index {@code i} as its first + * argument, and the given update as the second argument. + * + * @param i the index + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final E accumulateAndGet(int i, E x, + BinaryOperator accumulatorFunction) { + long offset = checkedByteOffset(i); + E prev, next; + do { + prev = getRaw(offset); + next = accumulatorFunction.operate(prev, x); + } while (!compareAndSetRaw(offset, prev, next)); + return next; + } + /** * Returns the String representation of the current values of array. * @return the String representation of the current values of array diff -r 379788c73130 -r c884f548a25f jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Wed Jan 16 10:14:09 2013 +0000 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Wed Jan 16 12:09:35 2013 +0000 @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.UnaryOperator; +import java.util.function.BinaryOperator; import sun.misc.Unsafe; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -183,6 +185,96 @@ return prev; } + /** + * Atomically updates the field of the given object managed by this updater + * with the results of applying the given function, returning the previous + * value. The function should be side-effect-free, since it may be + * re-applied when attempted updates fail due to contention among threads. + * + * @param obj An object whose field to get and set + * @param updateFunction a side-effect-free function + * @return the previous value + * @since 1.8 + */ + public final V getAndUpdate(T obj, UnaryOperator updateFunction) { + V prev, next; + do { + prev = get(obj); + next = updateFunction.operate(prev); + } while (!compareAndSet(obj, prev, next)); + return prev; + } + + /** + * Atomically updates the field of the given object managed by this updater + * with the results of applying the given function, returning the updated + * value. The function should be side-effect-free, since it may be + * re-applied when attempted updates fail due to contention among threads. + * + * @param obj An object whose field to get and set + * @param updateFunction a side-effect-free function + * @return the updated value + * @since 1.8 + */ + public final V updateAndGet(T obj, UnaryOperator updateFunction) { + V prev, next; + do { + prev = get(obj); + next = updateFunction.operate(prev); + } while (!compareAndSet(obj, prev, next)); + return next; + } + + /** + * Atomically updates the field of the given object managed by this + * updater with the results of applying the given function to the + * current and given values, returning the previous value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. The + * function is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param obj An object whose field to get and set + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the previous value + * @since 1.8 + */ + public final V getAndAccumulate(T obj, V x, + BinaryOperator accumulatorFunction) { + V prev, next; + do { + prev = get(obj); + next = accumulatorFunction.operate(prev, x); + } while (!compareAndSet(obj, prev, next)); + return prev; + } + + /** + * Atomically updates the field of the given object managed by this + * updater with the results of applying the given function to the + * current and given values, returning the updated value. The + * function should be side-effect-free, since it may be re-applied + * when attempted updates fail due to contention among threads. The + * function is applied with the current value as its first argument, + * and the given update as the second argument. + * + * @param obj An object whose field to get and set + * @param x the update value + * @param accumulatorFunction a side-effect-free function of two arguments + * @return the updated value + * @since 1.8 + */ + public final V accumulateAndGet(T obj, V x, + BinaryOperator accumulatorFunction) { + V prev, next; + do { + prev = get(obj); + next = accumulatorFunction.operate(prev, x); + } while (!compareAndSet(obj, prev, next)); + return next; + } + private static final class AtomicReferenceFieldUpdaterImpl extends AtomicReferenceFieldUpdater { private static final Unsafe unsafe = Unsafe.getUnsafe();