ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/CountedCompleterTest.java
(Generate patch)

Comparing jsr166/src/test/tck/CountedCompleterTest.java (file contents):
Revision 1.27 by jsr166, Sun Oct 18 19:33:21 2015 UTC vs.
Revision 1.28 by jsr166, Mon Aug 29 19:13:16 2016 UTC

# Line 13 | Line 13 | import java.util.concurrent.CountedCompl
13   import java.util.concurrent.ExecutionException;
14   import java.util.concurrent.ForkJoinPool;
15   import java.util.concurrent.ForkJoinTask;
16 + import java.util.concurrent.ThreadLocalRandom;
17   import java.util.concurrent.TimeoutException;
18   import java.util.concurrent.atomic.AtomicInteger;
19   import java.util.concurrent.atomic.AtomicReference;
20 + import java.util.function.BiConsumer;
21 + import java.util.function.Consumer;
22  
23   import junit.framework.Test;
24   import junit.framework.TestSuite;
# Line 1842 | Line 1845 | public class CountedCompleterTest extend
1845          testInvokeOnPool(singletonPool(), a);
1846      }
1847  
1848 +    /** CountedCompleter class javadoc code sample, version 1. */
1849 +    public static <E> void forEach1(E[] array, Consumer<E> action) {
1850 +        class Task extends CountedCompleter<Void> {
1851 +            final int lo, hi;
1852 +            Task(Task parent, int lo, int hi) {
1853 +                super(parent); this.lo = lo; this.hi = hi;
1854 +            }
1855 +
1856 +            public void compute() {
1857 +                if (hi - lo >= 2) {
1858 +                    int mid = (lo + hi) >>> 1;
1859 +                    // must set pending count before fork
1860 +                    setPendingCount(2);
1861 +                    new Task(this, mid, hi).fork(); // right child
1862 +                    new Task(this, lo, mid).fork(); // left child
1863 +                }
1864 +                else if (hi > lo)
1865 +                    action.accept(array[lo]);
1866 +                tryComplete();
1867 +            }
1868 +        }
1869 +        new Task(null, 0, array.length).invoke();
1870 +    }
1871 +
1872 +    /** CountedCompleter class javadoc code sample, version 2. */
1873 +    public static <E> void forEach2(E[] array, Consumer<E> action) {
1874 +        class Task extends CountedCompleter<Void> {
1875 +            final int lo, hi;
1876 +            Task(Task parent, int lo, int hi) {
1877 +                super(parent); this.lo = lo; this.hi = hi;
1878 +            }
1879 +
1880 +            public void compute() {
1881 +                if (hi - lo >= 2) {
1882 +                    int mid = (lo + hi) >>> 1;
1883 +                    setPendingCount(1); // not off by one !
1884 +                    new Task(this, mid, hi).fork(); // right child
1885 +                    new Task(this, lo, mid).compute(); // direct invoke
1886 +                } else {
1887 +                    if (hi > lo)
1888 +                        action.accept(array[lo]);
1889 +                    tryComplete();
1890 +                }
1891 +            }
1892 +        }
1893 +        new Task(null, 0, array.length).invoke();
1894 +    }
1895 +
1896 +    /** CountedCompleter class javadoc code sample, version 3. */
1897 +    public static <E> void forEach3(E[] array, Consumer<E> action) {
1898 +        class Task extends CountedCompleter<Void> {
1899 +            final int lo, hi;
1900 +            Task(Task parent, int lo, int hi) {
1901 +                super(parent); this.lo = lo; this.hi = hi;
1902 +            }
1903 +
1904 +            public void compute() {
1905 +                int n = hi - lo;
1906 +                for (; n >= 2; n /= 2) {
1907 +                    addToPendingCount(1);
1908 +                    new Task(this, lo + n/2, lo + n).fork();
1909 +                }
1910 +                if (n > 0)
1911 +                    action.accept(array[lo]);
1912 +                propagateCompletion();
1913 +            }
1914 +        }
1915 +        new Task(null, 0, array.length).invoke();
1916 +    }
1917 +
1918 +    /** CountedCompleter class javadoc code sample, version 4. */
1919 +    public static <E> void forEach4(E[] array, Consumer<E> action) {
1920 +        class Task extends CountedCompleter<Void> {
1921 +            final int lo, hi;
1922 +            Task(Task parent, int lo, int hi) {
1923 +                super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo));
1924 +                this.lo = lo; this.hi = hi;
1925 +            }
1926 +
1927 +            public void compute() {
1928 +                for (int n = hi - lo; n >= 2; n /= 2)
1929 +                    new Task(this, lo + n/2, lo + n).fork();
1930 +                action.accept(array[lo]);
1931 +                propagateCompletion();
1932 +            }
1933 +        }
1934 +        if (array.length > 0)
1935 +            new Task(null, 0, array.length).invoke();
1936 +    }
1937 +
1938 +    void testRecursiveDecomposition(
1939 +        BiConsumer<Integer[], Consumer<Integer>> action) {
1940 +        int n = ThreadLocalRandom.current().nextInt(8);
1941 +        Integer[] a = new Integer[n];
1942 +        for (int i = 0; i < n; i++) a[i] = i + 1;
1943 +        AtomicInteger ai = new AtomicInteger(0);
1944 +        action.accept(a, (x) -> ai.addAndGet(x));
1945 +        assertEquals(n * (n + 1) / 2, ai.get());
1946 +    }
1947 +
1948 +    /**
1949 +     * Variants of divide-by-two recursive decomposition into leaf tasks,
1950 +     * as described in the CountedCompleter class javadoc code samples
1951 +     */
1952 +    public void testRecursiveDecomposition() {
1953 +        testRecursiveDecomposition(CountedCompleterTest::forEach1);
1954 +        testRecursiveDecomposition(CountedCompleterTest::forEach2);
1955 +        testRecursiveDecomposition(CountedCompleterTest::forEach3);
1956 +        testRecursiveDecomposition(CountedCompleterTest::forEach4);
1957 +    }
1958 +
1959   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines