• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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