1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package org.openjdk.tests.java.util.stream; 27 28 import org.testng.annotations.Test; 29 30 import java.util.Comparator; 31 import java.util.Spliterator; 32 import java.util.concurrent.ForkJoinPool; 33 import java.util.concurrent.ForkJoinTask; 34 import java.util.concurrent.atomic.AtomicInteger; 35 import java.util.function.Consumer; 36 import java.util.stream.IntStream; 37 import java.util.stream.StreamSupport; 38 39 import static org.testng.Assert.assertEquals; 40 import static org.testng.Assert.assertTrue; 41 42 /** 43 * Tests stream execution in a custom ForkJoinPool. See JDK-8190974. 44 */ 45 @Test 46 public class CustomFJPoolTest { 47 48 // A Spliterator that counts the number of spliterators created 49 // including itself, thus the count starts at 1 50 static class SplitCountingSpliterator<T> implements Spliterator<T> { 51 final Spliterator<T> s; 52 final AtomicInteger nsplits; 53 54 // Top-level constructor SplitCountingSpliterator(Spliterator<T> s)55 public SplitCountingSpliterator(Spliterator<T> s) { 56 this.s = s; 57 nsplits = new AtomicInteger(1); 58 } 59 60 // Splitting constructor SplitCountingSpliterator(Spliterator<T> s, AtomicInteger nsplits)61 SplitCountingSpliterator(Spliterator<T> s, AtomicInteger nsplits) { 62 this.s = s; 63 this.nsplits = nsplits; 64 } 65 splits()66 int splits() { 67 return nsplits.get(); 68 } 69 70 @Override 71 tryAdvance(Consumer<? super T> action)72 public boolean tryAdvance(Consumer<? super T> action) { 73 return s.tryAdvance(action); 74 } 75 76 @Override forEachRemaining(Consumer<? super T> action)77 public void forEachRemaining(Consumer<? super T> action) { 78 s.forEachRemaining(action); 79 } 80 81 @Override trySplit()82 public Spliterator<T> trySplit() { 83 Spliterator<T> split = s.trySplit(); 84 if (split != null) { 85 nsplits.incrementAndGet(); 86 return new SplitCountingSpliterator<>(split, nsplits); 87 } 88 else { 89 return null; 90 } 91 } 92 93 @Override estimateSize()94 public long estimateSize() { 95 return s.estimateSize(); 96 } 97 98 @Override getExactSizeIfKnown()99 public long getExactSizeIfKnown() { 100 return s.getExactSizeIfKnown(); 101 } 102 103 @Override characteristics()104 public int characteristics() { 105 return s.characteristics(); 106 } 107 108 @Override hasCharacteristics(int characteristics)109 public boolean hasCharacteristics(int characteristics) { 110 return s.hasCharacteristics(characteristics); 111 } 112 113 @Override getComparator()114 public Comparator<? super T> getComparator() { 115 return s.getComparator(); 116 } 117 } 118 testCustomPools()119 public void testCustomPools() throws Exception { 120 int splitsForP1 = countSplits(new ForkJoinPool(1)); 121 int splitsForP2 = countSplits(new ForkJoinPool(2)); 122 assertEquals(splitsForP2, splitsForP1 * 2); 123 124 int commonParallelism = ForkJoinPool.getCommonPoolParallelism(); 125 if (commonParallelism > 1 && commonParallelism < 128) { 126 int splitsForPHalfC = countSplits(new ForkJoinPool(commonParallelism / 2)); 127 int splitsForPC = countSplits(ForkJoinPool.commonPool()); 128 129 assertTrue(splitsForPHalfC < splitsForPC); 130 assertEquals(splitsForPC / splitsForPHalfC, 131 nearestPowerOfTwo(commonParallelism) / nearestPowerOfTwo(commonParallelism / 2)); 132 } 133 } 134 135 static int countSplits(ForkJoinPool fjp) throws Exception { 136 // The number of splits will be equivalent to the number of leaf nodes 137 // and will be a power of 2 138 ForkJoinTask<Integer> fInteger = fjp.submit(() -> { 139 Spliterator<Integer> s = IntStream.range(0, 1024).boxed().parallel().spliterator(); 140 SplitCountingSpliterator<Integer> cs = new SplitCountingSpliterator<>(s); 141 StreamSupport.stream(cs, true).forEach(e -> {}); 142 return cs.splits(); 143 }); 144 return fInteger.get(); 145 } 146 nearestPowerOfTwo(int i)147 static int nearestPowerOfTwo(int i) { 148 return (i & (i - 1)) == 0 149 ? i 150 : 1 << (32 - Integer.numberOfLeadingZeros(i)); 151 } 152 } 153