From dcc8fbec729b9ce27338c1cc6f1c492471a2fe8d Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Wed, 16 Jan 2013 12:09:35 +0000
Subject: [PATCH] 8001666: Add lambda-compatible atomics and accumulators to
the ActomicXXX classes
Co-authored-by: Chris Hegarty
Reviewed-by: dl, chegar, darcy, goetz
---
.../util/concurrent/atomic/AtomicInteger.java | 88 +++++++++++++++++
.../concurrent/atomic/AtomicIntegerArray.java | 96 +++++++++++++++++++
.../atomic/AtomicIntegerFieldUpdater.java | 92 ++++++++++++++++++
.../util/concurrent/atomic/AtomicLong.java | 88 +++++++++++++++++
.../concurrent/atomic/AtomicLongArray.java | 96 +++++++++++++++++++
.../atomic/AtomicLongFieldUpdater.java | 92 ++++++++++++++++++
.../concurrent/atomic/AtomicReference.java | 88 +++++++++++++++++
.../atomic/AtomicReferenceArray.java | 96 +++++++++++++++++++
.../atomic/AtomicReferenceFieldUpdater.java | 92 ++++++++++++++++++
9 files changed, 828 insertions(+)
diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java
index f1c76b02bff..b48ef72dfc9 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java
index b5578ed93d8..6e4d226ba80 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index e2ae9c4f5dd..fcd5dd05f28 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java
index b38cf041fbb..2e58d29b211 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java
index 9651426c750..2536a9b8e93 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index a013680ce7a..a7672263a77 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java
index 94c9edca52a..95b88d127e2 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
index 71308618541..3e6ce969847 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index 78c636956f6..a92d914ff77 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/jdk/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();