diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java index f1c76b02bff5fb565c57fe1ef55dac07710fb714..b48ef72dfc97ccb9c3b2256b3fb47a535443058b 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.IntUnaryOperator; +import java.util.function.IntBinaryOperator; import sun.misc.Unsafe; /** @@ -203,6 +205,92 @@ public class AtomicInteger extends Number implements java.io.Serializable { return getAndAdd(delta) + delta; } + /** + * 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 --git a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java index b5578ed93d898552c74fac304488a8f038d8a3c4..6e4d226ba80d5beaf02fd1167a88f43652f72128 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.IntUnaryOperator; +import java.util.function.IntBinaryOperator; import sun.misc.Unsafe; /** @@ -245,6 +247,100 @@ public class AtomicIntegerArray implements java.io.Serializable { return getAndAdd(i, delta) + delta; } + /** + * 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 --git a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index e2ae9c4f5ddced6373f78b2604eda82315c68416..fcd5dd05f28a02cc90a4880ebec70b62846176ab 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -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; @@ -264,6 +266,96 @@ public abstract class AtomicIntegerFieldUpdater { 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 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 */ diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicLong.java b/src/share/classes/java/util/concurrent/atomic/AtomicLong.java index b38cf041fbbd54e757260cbf68188eba30df71ef..2e58d29b211066ef18d72d9f724a691a95dc69c9 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLong.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLong.java @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.LongUnaryOperator; +import java.util.function.LongBinaryOperator; import sun.misc.Unsafe; /** @@ -217,6 +219,92 @@ public class AtomicLong extends Number implements java.io.Serializable { return getAndAdd(delta) + delta; } + /** + * 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 --git a/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java index 9651426c7508d17169aeac49c8fc633a91c472b1..2536a9b8e93b4863bf6174510396c33e3c71c00c 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.LongUnaryOperator; +import java.util.function.LongBinaryOperator; import sun.misc.Unsafe; /** @@ -244,6 +246,100 @@ public class AtomicLongArray implements java.io.Serializable { return getAndAdd(i, delta) + delta; } + /** + * 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 --git a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index a013680ce7a03eac9fef46c75c57dc25d5b1d71f..a7672263a777e4c7bea25cc336d421db2104f580 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -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 @@ public abstract class AtomicLongFieldUpdater { 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 --git a/src/share/classes/java/util/concurrent/atomic/AtomicReference.java b/src/share/classes/java/util/concurrent/atomic/AtomicReference.java index 94c9edca52a65ac15e85676bf7b54c6a6c42355a..95b88d127e29037e0f1735e2d23ad2bc5d6c68ee 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReference.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReference.java @@ -34,6 +34,8 @@ */ package java.util.concurrent.atomic; +import java.util.function.UnaryOperator; +import java.util.function.BinaryOperator; import sun.misc.Unsafe; /** @@ -141,6 +143,92 @@ public class AtomicReference implements java.io.Serializable { return (V)unsafe.getAndSetObject(this, valueOffset, newValue); } + /** + * 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 --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index 71308618541b39253f854fe8c9296c3c72b2dabe..3e6ce969847d4bf6883f9b29e23a4ecc51d07a7e 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -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 @@ public class AtomicReferenceArray implements java.io.Serializable { 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 --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index 78c636956f6446fcb5e6e3889adfc297a61ec55f..a92d914ff77c0333ac99853424e403edc120f43c 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -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 @@ public abstract class AtomicReferenceFieldUpdater { 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();