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 with assistance from members of JCP JSR-166
  30  * Expert Group and released to the public domain, as explained at
  31  * http://creativecommons.org/publicdomain/zero/1.0/
  32  */
  33 
  34 /*
  35  * @test
  36  * @bug 8008378
  37  * @summary Basic checks for parallelism 0, and null returning factory
  38  * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 ThreadLessCommon
  39  * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.threadFactory=ThreadLessCommon$NullForkJoinWorkerThreadFactory ThreadLessCommon
  40  * @author Chris Hegarty
  41  */
  42 
  43 import java.util.concurrent.ForkJoinPool;
  44 import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
  45 import java.util.concurrent.ForkJoinWorkerThread;
  46 import java.util.concurrent.RecursiveTask;
  47 
  48 public class ThreadLessCommon {
  49 
  50     static final int THRESHOLD = 1000;
  51     static final boolean debug = true;
  52 
  53     private static void realMain(String[] args) throws Throwable {
  54         if (debug) {
  55             String pp = System.getProperty(
  56                     "java.util.concurrent.ForkJoinPool.common.parallelism");
  57             System.out.println(
  58                     "java.util.concurrent.ForkJoinPool.common.parallelism:" + pp);
  59             String tf = System.getProperty(
  60                     "java.util.concurrent.ForkJoinPool.common.threadFactory");
  61             System.out.println(
  62                     "java.util.concurrent.ForkJoinPool.common.threadFactory:" + tf);
  63         }
  64 
  65         long from = 0, to = 50000;
  66         RecursiveTask<Long> task = new SumTask(from, to, Thread.currentThread());
  67         long sum = task.invoke();
  68         System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum);
  69 
  70         task.fork();
  71         sum = task.join();
  72         System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum);
  73 
  74         sum = ForkJoinPool.commonPool().invoke(task.fork());
  75         System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum);
  76     }
  77 
  78     static class SumTask extends RecursiveTask<Long> {
  79         final Thread expectedThread;
  80         final long from;
  81         final long to;
  82         SumTask(long from, long to, Thread thread) {
  83             this.from = from; this.to = to; expectedThread = thread;
  84         }
  85 
  86         @Override
  87         public Long compute() {
  88             check(Thread.currentThread() == expectedThread,
  89                   "Expected " + expectedThread + ", got " + Thread.currentThread());
  90             long range = to - from;
  91             if (range < THRESHOLD) {
  92                 long acc = 0;
  93                 for (long i = from; i <= to; i++)
  94                     acc = acc + i;
  95                 return acc;
  96             } else {
  97                 long half = from + range / 2;
  98                 SumTask t1 = new SumTask(from, half ,expectedThread);
  99                 SumTask t2 = new SumTask(half+1, to ,expectedThread);
 100                 if (half % 2 == 0) {
 101                     t1.fork();
 102                     return t2.compute() + t1.join();
 103                 } else {
 104                     invokeAll(t1, t2);
 105                     try { return t1.get() + t2.get(); }
 106                     catch (Exception x) { unexpected(x); return 0L;}
 107                 }
 108             }
 109         }
 110     }
 111 
 112     public static class NullForkJoinWorkerThreadFactory
 113         implements ForkJoinWorkerThreadFactory
 114     {
 115         @Override
 116         public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
 117             return null;
 118         }
 119     }
 120 
 121     //--------------------- Infrastructure ---------------------------
 122     static volatile int passed = 0, failed = 0;
 123     static void pass() {passed++;}
 124     static void fail() {failed++; /*Thread.dumpStack();*/}
 125     static void fail(String msg) {System.out.println(msg); fail();}
 126     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
 127     static void check(boolean cond, String msg) {if (cond) pass(); else fail(msg);}
 128     static void equal(Object x, Object y) {
 129         if (x == null ? y == null : x.equals(y)) pass();
 130         else fail(x + " not equal to " + y);}
 131     public static void main(String[] args) throws Throwable {
 132         try {realMain(args);} catch (Throwable t) {unexpected(t);}
 133         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
 134         if (failed > 0) throw new AssertionError("Some tests failed");}
 135 }