1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 */ 22 23 /* 24 * This file is available under and governed by the GNU General Public 25 * License version 2 only, as published by the Free Software Foundation. 26 * However, the following notice accompanied the original version of this 27 * file: 28 * 29 * Written by Doug Lea and Martin Buchholz with assistance from 30 * members of JCP JSR-166 Expert Group and released to the public 31 * domain, as explained at 32 * http://creativecommons.org/publicdomain/zero/1.0/ 33 */ 34 35 package test.java.util.concurrent.tck; 36 import static java.util.concurrent.TimeUnit.MILLISECONDS; 37 import static java.util.concurrent.TimeUnit.SECONDS; 38 import static org.junit.Assert.assertEquals; 39 import static org.junit.Assert.assertFalse; 40 import static org.junit.Assert.assertNull; 41 import static org.junit.Assert.assertNotNull; 42 import static org.junit.Assert.assertSame; 43 import static org.junit.Assert.assertNotSame; 44 import static org.junit.Assert.assertTrue; 45 import static org.junit.Assert.fail; 46 47 import java.util.concurrent.CountedCompleter; 48 import java.util.concurrent.ThreadLocalRandom; 49 import java.util.concurrent.atomic.AtomicInteger; 50 import java.util.function.BiConsumer; 51 import java.util.function.Consumer; 52 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.junit.runners.JUnit4; 56 57 // Android-changed: Use JUnit4. 58 @RunWith(JUnit4.class) 59 public class CountedCompleter8Test extends JSR166TestCase { 60 // Android-changed: Use JUnitCore.main. main(String[] args)61 public static void main(String[] args) { 62 // main(suite(), args); 63 org.junit.runner.JUnitCore.main("test.java.util.concurrent.tck.CountedCompleter8Test"); 64 } 65 // public static Test suite() { 66 // return new TestSuite(CountedCompleter8Test.class); 67 // } 68 69 /** CountedCompleter class javadoc code sample, version 1. */ forEach1(E[] array, Consumer<E> action)70 public static <E> void forEach1(E[] array, Consumer<E> action) { 71 class Task extends CountedCompleter<Void> { 72 final int lo, hi; 73 Task(Task parent, int lo, int hi) { 74 super(parent); this.lo = lo; this.hi = hi; 75 } 76 77 public void compute() { 78 if (hi - lo >= 2) { 79 int mid = (lo + hi) >>> 1; 80 // must set pending count before fork 81 setPendingCount(2); 82 new Task(this, mid, hi).fork(); // right child 83 new Task(this, lo, mid).fork(); // left child 84 } 85 else if (hi > lo) 86 action.accept(array[lo]); 87 tryComplete(); 88 } 89 } 90 new Task(null, 0, array.length).invoke(); 91 } 92 93 /** CountedCompleter class javadoc code sample, version 2. */ forEach2(E[] array, Consumer<E> action)94 public static <E> void forEach2(E[] array, Consumer<E> action) { 95 class Task extends CountedCompleter<Void> { 96 final int lo, hi; 97 Task(Task parent, int lo, int hi) { 98 super(parent); this.lo = lo; this.hi = hi; 99 } 100 101 public void compute() { 102 if (hi - lo >= 2) { 103 int mid = (lo + hi) >>> 1; 104 setPendingCount(1); // looks off by one, but correct! 105 new Task(this, mid, hi).fork(); // right child 106 new Task(this, lo, mid).compute(); // direct invoke 107 } else { 108 if (hi > lo) 109 action.accept(array[lo]); 110 tryComplete(); 111 } 112 } 113 } 114 new Task(null, 0, array.length).invoke(); 115 } 116 117 /** CountedCompleter class javadoc code sample, version 3. */ forEach3(E[] array, Consumer<E> action)118 public static <E> void forEach3(E[] array, Consumer<E> action) { 119 class Task extends CountedCompleter<Void> { 120 final int lo, hi; 121 Task(Task parent, int lo, int hi) { 122 super(parent); this.lo = lo; this.hi = hi; 123 } 124 125 public void compute() { 126 int n = hi - lo; 127 for (; n >= 2; n /= 2) { 128 addToPendingCount(1); 129 new Task(this, lo + n/2, lo + n).fork(); 130 } 131 if (n > 0) 132 action.accept(array[lo]); 133 propagateCompletion(); 134 } 135 } 136 new Task(null, 0, array.length).invoke(); 137 } 138 139 /** CountedCompleter class javadoc code sample, version 4. */ forEach4(E[] array, Consumer<E> action)140 public static <E> void forEach4(E[] array, Consumer<E> action) { 141 class Task extends CountedCompleter<Void> { 142 final int lo, hi; 143 Task(Task parent, int lo, int hi) { 144 super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo)); 145 this.lo = lo; this.hi = hi; 146 } 147 148 public void compute() { 149 for (int n = hi - lo; n >= 2; n /= 2) 150 new Task(this, lo + n/2, lo + n).fork(); 151 action.accept(array[lo]); 152 propagateCompletion(); 153 } 154 } 155 if (array.length > 0) 156 new Task(null, 0, array.length).invoke(); 157 } 158 testRecursiveDecomposition( BiConsumer<Integer[], Consumer<Integer>> action)159 private void testRecursiveDecomposition( 160 BiConsumer<Integer[], Consumer<Integer>> action) { 161 int n = ThreadLocalRandom.current().nextInt(8); 162 Integer[] a = new Integer[n]; 163 for (int i = 0; i < n; i++) a[i] = i + 1; 164 AtomicInteger ai = new AtomicInteger(0); 165 action.accept(a, ai::addAndGet); 166 assertEquals(n * (n + 1) / 2, ai.get()); 167 } 168 169 /** 170 * Variants of divide-by-two recursive decomposition into leaf tasks, 171 * as described in the CountedCompleter class javadoc code samples 172 */ 173 @Test testRecursiveDecomposition()174 public void testRecursiveDecomposition() { 175 testRecursiveDecomposition(CountedCompleter8Test::forEach1); 176 testRecursiveDecomposition(CountedCompleter8Test::forEach2); 177 testRecursiveDecomposition(CountedCompleter8Test::forEach3); 178 testRecursiveDecomposition(CountedCompleter8Test::forEach4); 179 } 180 181 } 182