sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1812824 - in /sis/branches/JDK8/core/sis-utility/src: main/java/org/apache/sis/util/collection/IntegerList.java test/java/org/apache/sis/test/Assert.java test/java/org/apache/sis/util/collection/IntegerListTest.java
Date Sat, 21 Oct 2017 13:40:54 GMT
Author: desruisseaux
Date: Sat Oct 21 13:40:54 2017
New Revision: 1812824

URL: http://svn.apache.org/viewvc?rev=1812824&view=rev
Log:
Implement IntegerList.PrimitiveSpliterator.trySplit() for parallelization.

Modified:
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/IntegerList.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/util/collection/IntegerListTest.java

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/IntegerList.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/IntegerList.java?rev=1812824&r1=1812823&r2=1812824&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/IntegerList.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/collection/IntegerList.java
[UTF-8] Sat Oct 21 13:40:54 2017
@@ -470,19 +470,20 @@ public class IntegerList extends Abstrac
     }
 
     /**
-     * Returns a sequential stream of integers with this {@code IntegerList} as its source.
+     * Returns a stream of integers with this {@code IntegerList} as its source.
      * This method is similar to {@link #stream()}, but does not box the values.
      * The returned stream is <cite>fail-fast</cite>, meaning that any modification
to the list
      * while using the stream will cause a {@link ConcurrentModificationException} to be
thrown.
      *
-     * <p>The default implementation creates a sequential stream from {@link #spliterator()}.</p>
+     * <p>The default implementation creates a parallel or sequential stream from {@link
#spliterator()}.</p>
      *
+     * @param parallel  {@code true} for a parallel stream, or {@code false} for a sequential
stream.
      * @return a stream of values in this list as primitive types.
      *
      * @since 0.8-jdk8
      */
-    public IntStream ints() {
-        return StreamSupport.intStream(spliterator(), false);
+    public IntStream ints(boolean parallel) {
+        return StreamSupport.intStream(spliterator(), parallel);
     }
 
     /**
@@ -497,6 +498,12 @@ public class IntegerList extends Abstrac
      */
     private final class PrimitiveSpliterator implements Spliterator.OfInt, PrimitiveIterator.OfInt
{
         /**
+         * Index after the last element returned by this spliterator. This is initially {@link
IntegerList#size},
+         * but may be set to a smaller value by call to {@link #trySplit()}.
+         */
+        private int stopAt;
+
+        /**
          * Index of the next element to be returned.
          */
         private int nextIndex;
@@ -519,6 +526,19 @@ public class IntegerList extends Abstrac
          */
         PrimitiveSpliterator() {
             expectedModCount = modCount;
+            stopAt           = size;
+        }
+
+        /**
+         * Creates the prefix spliterator in a call to {@link #trySplit()}.
+         *
+         * @param  suffix   the spliterator which will continue iteration after this spliterator.
+         * @param  startAt  index of the first element to be returned by this prefix spliterator.
+         */
+        private PrimitiveSpliterator(final PrimitiveSpliterator suffix, final int startAt)
{
+            expectedModCount = suffix.expectedModCount;
+            stopAt           = suffix.nextIndex;
+            nextIndex        = startAt;
         }
 
         /**
@@ -528,15 +548,15 @@ public class IntegerList extends Abstrac
          */
         @Override
         public int characteristics() {
-            return NONNULL | ORDERED | SIZED;
+            return NONNULL | ORDERED | SIZED | SUBSIZED;
         }
 
         /**
-         * Returns the exact number of values in the backing list.
+         * Returns the exact number of values to be encountered by a {@code forEachRemaining(…)}
traversal.
          */
         @Override
         public long estimateSize() {
-            return size();
+            return stopAt - nextIndex;
         }
 
         /**
@@ -545,6 +565,12 @@ public class IntegerList extends Abstrac
          */
         @Override
         public Spliterator.OfInt trySplit() {
+            final int startAt = nextIndex;
+            final int halfSize = (stopAt - startAt) >>> 1;
+            if (halfSize > 1) {
+                nextIndex += halfSize;
+                return new PrimitiveSpliterator(this, startAt);
+            }
             return null;
         }
 
@@ -556,7 +582,7 @@ public class IntegerList extends Abstrac
         @Override
         public boolean hasNext() {
             if (modCount == expectedModCount) {
-                return nextIndex < size;
+                return nextIndex < stopAt;
             } else {
                 throw new ConcurrentModificationException();
             }
@@ -616,7 +642,7 @@ public class IntegerList extends Abstrac
          */
         @Override
         public void remove() {
-            if (nextIndex < lastRemove || nextIndex > size) {
+            if (nextIndex < lastRemove || nextIndex > stopAt) {
                 throw new IllegalStateException();
             }
             if (modCount != expectedModCount) {
@@ -625,6 +651,7 @@ public class IntegerList extends Abstrac
             expectedModCount = ++modCount;
             removeRange(nextIndex - 1, nextIndex);
             lastRemove = --nextIndex;
+            stopAt--;
         }
     }
 

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java?rev=1812824&r1=1812823&r2=1812824&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java [UTF-8]
(original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/Assert.java [UTF-8]
Sat Oct 21 13:40:54 2017
@@ -24,6 +24,8 @@ import java.util.Collection;
 import java.util.Enumeration;
 import java.util.LinkedHashSet;
 import java.util.LinkedHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -177,6 +179,7 @@ public strictfp class Assert extends org
 
     /**
      * Verifies that the given stream produces the same values than the given iterator, in
same order.
+     * This method assumes that the given stream is sequential.
      *
      * @param  <E>       the type of values to test.
      * @param  expected  the expected values.
@@ -184,7 +187,7 @@ public strictfp class Assert extends org
      *
      * @since 0.8
      */
-    public static <E> void assertStreamEquals(final Iterator<E> expected, final
Stream<E> actual) {
+    public static <E> void assertSequentialStreamEquals(final Iterator<E> expected,
final Stream<E> actual) {
         actual.forEach(new Consumer<E>() {
             private int count;
 
@@ -204,6 +207,48 @@ public strictfp class Assert extends org
     }
 
     /**
+     * Verifies that the given stream produces the same values than the given iterator, in
any order.
+     * This method is designed for use with parallel streams, but works with sequential streams
too.
+     *
+     * @param  <E>       the type of values to test.
+     * @param  expected  the expected values.
+     * @param  actual    the stream to compare with the expected values.
+     *
+     * @since 0.8
+     */
+    public static <E> void assertParallelStreamEquals(final Iterator<E> expected,
final Stream<E> actual) {
+        final Integer ONE = 1;          // For doing autoboxing only once.
+        final ConcurrentMap<E,Integer> count = new ConcurrentHashMap<>();
+        while (expected.hasNext()) {
+            count.merge(expected.next(), ONE, (old, one) -> old + 1);
+        }
+        /*
+         * Following may be parallelized in an arbitrary amount of threads.
+         */
+        actual.forEach((value) -> {
+            if (count.computeIfPresent(value, (key, old) -> old - 1) == null) {
+                fail("Stream returned unexpected value: " + value);
+            }
+        });
+        /*
+         * Back to sequential order, verify that all elements have been traversed
+         * by the stream and no more.
+         */
+        for (final Map.Entry<E,Integer> entry : count.entrySet()) {
+            int n = entry.getValue();
+            if (n != 0) {
+                final String message;
+                if (n < 0) {
+                    message = "Stream returned too many occurrences of %s%n%d extraneous
were found.";
+                } else {
+                    message = "Stream did not returned all expected occurrences of %s%n%d
are missing.";
+                }
+                fail(String.format(message, entry.getKey(), StrictMath.abs(n)));
+            }
+        }
+    }
+
+    /**
      * Asserts that the given set contains the same elements, ignoring order.
      * In case of failure, this method lists the missing or unexpected elements.
      *

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/util/collection/IntegerListTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/util/collection/IntegerListTest.java?rev=1812824&r1=1812823&r2=1812824&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/util/collection/IntegerListTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/util/collection/IntegerListTest.java
[UTF-8] Sat Oct 21 13:40:54 2017
@@ -99,7 +99,7 @@ public final strictfp class IntegerListT
          * use the PrimitiveSpliterator.forEachRemaining(Consumer<? super Integer>)
method. A more
          * specific test using forEachRemaining(IntConsumer) is done by the testInts() method.
          */
-        assertStreamEquals(copy.iterator(), list.stream());
+        assertSequentialStreamEquals(copy.iterator(), list.stream());
         /*
          * Tests cloning and removal of values in a range of indices. The IntegerList.removeRange(…)
          * method is invoked indirectly by subList(…).clear(). Again, we use ArrayList
as a reference.
@@ -234,11 +234,12 @@ public final strictfp class IntegerListT
 
     /**
      * Tests that primitive stream traversal is coherent with its list value.
+     * This method tests sequential stream only.
      */
     @Test
     public void testInts() {
         list = createRandomlyFilled(42, 404);
-        list.ints().forEach(new IntConsumer() {
+        list.ints(false).forEach(new IntConsumer() {
             private int index = 0;
 
             @Override
@@ -249,13 +250,22 @@ public final strictfp class IntegerListT
     }
 
     /**
+     * Tests that primitive stream traversal with parallelization.
+     */
+    @Test
+    public void testIntsParallel() {
+        list = createRandomlyFilled(80, 321);
+        assertParallelStreamEquals(list.iterator(), list.stream().parallel());
+    }
+
+    /**
      * Ensures our stream is a fail-fast operator, i.e: it fails when the list has
      * been modified before the end of its iteration.
      */
     @Test
     public void testErrorOnCoModification() {
         list = createRandomlyFilled(4, 10);
-        final PrimitiveIterator.OfInt values = list.ints().iterator();
+        final PrimitiveIterator.OfInt values = list.ints(false).iterator();
 
         // Start iteration normally.
         assertEquals(list.getInt(0), values.nextInt());



Mime
View raw message