changeset 6363:0afeaddee9cf

Add Iterator.forEach; add Atomic{Reference,Int,Loference,Int,Long}FieldUpdater.{getAndUpdate,updateAndGet}
author briangoetz
date Thu, 01 Nov 2012 12:19:07 -0400
parents 7bc844cd6603
children 0f187cdcacb3
files src/share/classes/java/util/Collection.java src/share/classes/java/util/Iterator.java src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java src/share/classes/java/util/streams/Spliterator.java src/share/classes/java/util/streams/StreamAccessor.java src/share/classes/java/util/streams/Streams.java src/share/classes/java/util/streams/ops/Nodes.java
diffstat 9 files changed, 155 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/Collection.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/Collection.java	Thu Nov 01 12:19:07 2012 -0400
@@ -466,7 +466,8 @@
      * removed.
      * @return {@code true} if any elements were removed.
      */
-    boolean removeIf(Predicate<? super E> filter) default {
+    boolean removeAll(Predicate<? super E> filter) default {
+        Objects.requireNonNull(filter);
         boolean removed = false;
         Iterator<E> each = iterator();
         while(each.hasNext()) {
--- a/src/share/classes/java/util/Iterator.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/Iterator.java	Thu Nov 01 12:19:07 2012 -0400
@@ -25,6 +25,8 @@
 
 package java.util;
 
+import java.util.functions.Block;
+
 /**
  * An iterator over a collection.  {@code Iterator} takes the place of
  * {@link Enumeration} in the Java Collections Framework.  Iterators
@@ -86,4 +88,14 @@
     void remove() default {
         throw new UnsupportedOperationException("remove");
     }
+
+    /**
+     * Execute the specified Block for each element
+     *
+     * @param block The Block to which elements will be provided
+     */
+    void forEach(Block<? super E> block) default {
+        while (hasNext())
+            block.apply(next());
+    }
 }
--- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Thu Nov 01 12:19:07 2012 -0400
@@ -40,6 +40,8 @@
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
+import java.util.functions.IntUnaryOperator;
+import java.util.functions.UnaryOperator;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -265,6 +267,46 @@
     }
 
     /**
+     * Sets the value by applying the supplied operator to the old value,
+     * and updating it atomically as in {@link #compareAndSet(T, int, int)}.
+     *
+     * If the update results in a collision, we back off and retry the update
+     * (using the new current value) until successful.
+     *
+     * @param obj An object whose field to update
+     * @param op the operator to use to compute the new value
+     * @return the new value
+     */
+    public final int updateAndGet(T obj, IntUnaryOperator op) {
+        int oldValue, newValue;
+        do {
+            oldValue = get(obj);
+            newValue = op.operate(oldValue);
+        } while (!compareAndSet(obj, oldValue, newValue));
+        return newValue;
+    }
+
+    /**
+     * Sets the value by applying the supplied operator to the old value,
+     * and updating it atomically as in {@link #compareAndSet(T, int, int)}.
+     *
+     * If the update results in a collision, we back off and retry the update
+     * (using the new current value) until successful.
+     *
+     * @param obj An object whose field to update
+     * @param op the operator to use to compute the new value
+     * @return the old value
+     */
+    public final int getAndUpdate(T obj, IntUnaryOperator op) {
+        int oldValue, newValue;
+        do {
+            oldValue = get(obj);
+            newValue = op.operate(oldValue);
+        } while (!compareAndSet(obj, oldValue, newValue));
+        return oldValue;
+    }
+
+    /**
      * Standard hotspot implementation using intrinsics
      */
     private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
--- a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Thu Nov 01 12:19:07 2012 -0400
@@ -40,6 +40,8 @@
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
+import java.util.functions.IntUnaryOperator;
+import java.util.functions.LongUnaryOperator;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -267,6 +269,46 @@
         }
     }
 
+    /**
+     * Sets the value by applying the supplied operator to the old value,
+     * and updating it atomically as in {@link #compareAndSet(T, long, long)}.
+     *
+     * If the update results in a collision, we back off and retry the update
+     * (using the new current value) until successful.
+     *
+     * @param obj An object whose field to update
+     * @param op the operator to use to compute the new value
+     * @return the new value
+     */
+    public final long updateAndGet(T obj, LongUnaryOperator op) {
+        long oldValue, newValue;
+        do {
+            oldValue = get(obj);
+            newValue = op.operate(oldValue);
+        } while (!compareAndSet(obj, oldValue, newValue));
+        return newValue;
+    }
+
+    /**
+     * Sets the value by applying the supplied operator to the old value,
+     * and updating it atomically as in {@link #compareAndSet(T, long, long)}.
+     *
+     * If the update results in a collision, we back off and retry the update
+     * (using the new current value) until successful.
+     *
+     * @param obj An object whose field to update
+     * @param op the operator to use to compute the new value
+     * @return the old value
+     */
+    public final long getAndUpdate(T obj, LongUnaryOperator op) {
+        long oldValue, newValue;
+        do {
+            oldValue = get(obj);
+            newValue = op.operate(oldValue);
+        } while (!compareAndSet(obj, oldValue, newValue));
+        return oldValue;
+    }
+
     private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
         private static final Unsafe unsafe = Unsafe.getUnsafe();
         private final long offset;
--- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Thu Nov 01 12:19:07 2012 -0400
@@ -40,6 +40,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
+import java.util.functions.UnaryOperator;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -183,6 +184,46 @@
         }
     }
 
+    /**
+     * Sets the value by applying the supplied operator to the old value,
+     * and updating it atomically as in {@link #compareAndSet(T, V, V)}.
+     *
+     * If the update results in a collision, we back off and retry the update
+     * (using the new current value) until successful.
+     *
+     * @param obj An object whose field to update
+     * @param op the operator to use to compute the new value
+     * @return the new value
+     */
+    public final V updateAndGet(T obj, UnaryOperator<V> op) {
+        V oldValue, newValue;
+        do {
+            oldValue = get(obj);
+            newValue = op.operate(oldValue);
+        } while (!compareAndSet(obj, oldValue, newValue));
+        return newValue;
+    }
+
+    /**
+     * Sets the value by applying the supplied operator to the old value,
+     * and updating it atomically as in {@link #compareAndSet(T, V, V)}.
+     *
+     * If the update results in a collision, we back off and retry the update
+     * (using the new current value) until successful.
+     *
+     * @param obj An object whose field to update
+     * @param op the operator to use to compute the new value
+     * @return the old value
+     */
+    public final V getAndUpdate(T obj, UnaryOperator<V> op) {
+        V oldValue, newValue;
+        do {
+            oldValue = get(obj);
+            newValue = op.operate(oldValue);
+        } while (!compareAndSet(obj, oldValue, newValue));
+        return oldValue;
+    }
+
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
         extends AtomicReferenceFieldUpdater<T,V> {
         private static final Unsafe unsafe = Unsafe.getUnsafe();
--- a/src/share/classes/java/util/streams/Spliterator.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/streams/Spliterator.java	Thu Nov 01 12:19:07 2012 -0400
@@ -80,7 +80,7 @@
      *
      * @param sink The sink to which elements will be provided.
      */
-    void forEach(Block<T> sink) default {
+    void forEach(Block<? super T> sink) default {
         Iterator<T> remaining = iterator();
         while (remaining.hasNext()) {
             sink.apply(remaining.next());
--- a/src/share/classes/java/util/streams/StreamAccessor.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/streams/StreamAccessor.java	Thu Nov 01 12:19:07 2012 -0400
@@ -41,7 +41,7 @@
      *
      * @param sink The sink to which elements will be provided.
      */
-    void forEach(Block<T> sink);
+    void forEach(Block<? super T> sink);
 
     /**
      * Return the iterator for the elements of this stream. The same iterator
--- a/src/share/classes/java/util/streams/Streams.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/streams/Streams.java	Thu Nov 01 12:19:07 2012 -0400
@@ -281,7 +281,7 @@
             }
 
             @Override
-            public void forEach(Block<Object> sink) {
+            public void forEach(Block<? super Object> sink) {
             }
 
             @Override
@@ -321,7 +321,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             while (it.hasNext())
                 sink.apply(it.next());
         }
@@ -370,7 +370,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             // Implementing this method would result in a infinite loop
             // @@@ No mechanism for ops to short circuit push loop
             // @@@ Spliterator to the rescue? arity of 1, n elements for lhs, rhs is always infinite
@@ -414,7 +414,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             spliterator.forEach(sink);
         }
 
@@ -478,7 +478,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             if (iterator == null) {
                 iterable.forEach(sink);
                 iterator = Collections.emptyIterator();
@@ -523,7 +523,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             if (iterator == null) {
                 col.forEach(sink);
                 iterator = Collections.emptyIterator();
@@ -633,7 +633,7 @@
             return ((T[]) proxy.getArray())[offset++];
         }
 
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             comodificationCheck();
 
             T[] elements = (T[]) proxy.getArray();
@@ -743,7 +743,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
            traversing = true;
            super.forEach(sink);
         }
@@ -816,7 +816,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             traversing = true;
             for (int i=offset; i<endOffset; i++) {
                 sink.apply(elements[i]);
@@ -875,7 +875,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             traversing = true;
             for (int i=offset; i<endOffset; i++) {
                 sink.apply(elements.get(i));
@@ -924,7 +924,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             for (int i=offset; i<endOffset; i++) {
                 sink.apply(elements[i]);
             }
@@ -992,7 +992,7 @@
         }
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             for (int i=offset; i<endOffset; i++) {
                 sink.apply(elements.get(i));
             }
--- a/src/share/classes/java/util/streams/ops/Nodes.java	Tue Oct 30 17:30:48 2012 -0700
+++ b/src/share/classes/java/util/streams/ops/Nodes.java	Thu Nov 01 12:19:07 2012 -0400
@@ -60,7 +60,7 @@
         // StreamAccessor
 
         @Override
-        public void forEach(Block<T> sink) {
+        public void forEach(Block<? super T> sink) {
             spliterator.forEach(sink);
         }
 
@@ -416,7 +416,7 @@
             }
 
             @Override
-            public void forEach(Block<T> sink) {
+            public void forEach(Block<? super T> sink) {
                 if (iterator == null) {
                     cur.forEach(sink);
                     iterator = Collections.emptyIterator();