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 import static java.util.concurrent.TimeUnit.MILLISECONDS; 35 36 import java.util.Arrays; 37 import java.util.concurrent.CountDownLatch; 38 import java.util.concurrent.ExecutionException; 39 import java.util.concurrent.ForkJoinPool; 40 import java.util.concurrent.ForkJoinTask; 41 import java.util.concurrent.ForkJoinWorkerThread; 42 import java.util.concurrent.RecursiveAction; 43 import java.util.concurrent.TimeoutException; 44 45 import junit.framework.Test; 46 import junit.framework.TestSuite; 47 48 public class ForkJoinTask8Test extends JSR166TestCase { 49 50 /* 51 * Testing notes: This differs from ForkJoinTaskTest mainly by 52 * defining a version of BinaryAsyncAction that uses JDK8 task 53 * tags for control state, thereby testing getForkJoinTaskTag, 54 * setForkJoinTaskTag, and compareAndSetForkJoinTaskTag across 55 * various contexts. Most of the test methods using it are 56 * otherwise identical, but omitting retest of those dealing with 57 * cancellation, which is not represented in this tag scheme. 58 */ 59 60 static final short INITIAL_STATE = -1; 61 static final short COMPLETE_STATE = 0; 62 static final short EXCEPTION_STATE = 1; 63 64 public static void main(String[] args) { 65 main(suite(), args); 66 } 67 68 public static Test suite() { 69 return new TestSuite(ForkJoinTask8Test.class); 70 } 71 72 // Runs with "mainPool" use > 1 thread. singletonPool tests use 1 73 static final int mainPoolSize = 74 Math.max(2, Runtime.getRuntime().availableProcessors()); 75 76 private static ForkJoinPool mainPool() { 77 return new ForkJoinPool(mainPoolSize); 78 } 79 80 private static ForkJoinPool singletonPool() { 81 return new ForkJoinPool(1); 82 } 83 84 private static ForkJoinPool asyncSingletonPool() { 85 return new ForkJoinPool(1, 86 ForkJoinPool.defaultForkJoinWorkerThreadFactory, 87 null, true); 88 } 89 90 // Compute fib naively and efficiently 91 final int[] fib; 92 { 93 int[] fib = new int[10]; 94 fib[0] = 0; 95 fib[1] = 1; 96 for (int i = 2; i < fib.length; i++) 97 fib[i] = fib[i - 1] + fib[i - 2]; 98 this.fib = fib; 99 } 100 101 private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) { 102 try (PoolCleaner cleaner = cleaner(pool)) { 103 assertFalse(a.isDone()); 104 assertFalse(a.isCompletedNormally()); 105 assertFalse(a.isCompletedAbnormally()); 106 assertFalse(a.isCancelled()); 107 assertNull(a.getException()); 108 assertNull(a.getRawResult()); 109 110 assertNull(pool.invoke(a)); 111 112 assertTrue(a.isDone()); 113 assertTrue(a.isCompletedNormally()); 114 assertFalse(a.isCompletedAbnormally()); 115 assertFalse(a.isCancelled()); 116 assertNull(a.getException()); 117 assertNull(a.getRawResult()); 118 } 119 } 120 121 void checkNotDone(ForkJoinTask a) { 122 assertFalse(a.isDone()); 123 assertFalse(a.isCompletedNormally()); 124 assertFalse(a.isCompletedAbnormally()); 125 assertFalse(a.isCancelled()); 126 assertNull(a.getException()); 127 assertNull(a.getRawResult()); 128 if (a instanceof BinaryAsyncAction) 129 assertEquals(INITIAL_STATE, 130 ((BinaryAsyncAction)a).getForkJoinTaskTag()); 131 132 try { 133 a.get(randomExpiredTimeout(), randomTimeUnit()); 134 shouldThrow(); 135 } catch (TimeoutException success) { 136 } catch (Throwable fail) { threadUnexpectedException(fail); } 137 } 138 139 <T> void checkCompletedNormally(ForkJoinTask<T> a) { 140 checkCompletedNormally(a, null); 141 } 142 143 <T> void checkCompletedNormally(ForkJoinTask<T> a, T expected) { 144 assertTrue(a.isDone()); 145 assertFalse(a.isCancelled()); 146 assertTrue(a.isCompletedNormally()); 147 assertFalse(a.isCompletedAbnormally()); 148 assertNull(a.getException()); 149 assertSame(expected, a.getRawResult()); 150 if (a instanceof BinaryAsyncAction) 151 assertEquals(COMPLETE_STATE, 152 ((BinaryAsyncAction)a).getForkJoinTaskTag()); 153 154 { 155 Thread.currentThread().interrupt(); 156 long startTime = System.nanoTime(); 157 assertSame(expected, a.join()); 158 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); 159 Thread.interrupted(); 160 } 161 162 { 163 Thread.currentThread().interrupt(); 164 long startTime = System.nanoTime(); 165 a.quietlyJoin(); // should be no-op 166 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); 167 Thread.interrupted(); 168 } 169 170 assertFalse(a.cancel(false)); 171 assertFalse(a.cancel(true)); 172 try { 173 assertSame(expected, a.get()); 174 assertSame(expected, a.get(randomTimeout(), randomTimeUnit())); 175 } catch (Throwable fail) { threadUnexpectedException(fail); } 176 } 177 178 void checkCompletedAbnormally(ForkJoinTask a, Throwable t) { 179 assertTrue(a.isDone()); 180 assertFalse(a.isCancelled()); 181 assertFalse(a.isCompletedNormally()); 182 assertTrue(a.isCompletedAbnormally()); 183 assertSame(t.getClass(), a.getException().getClass()); 184 assertNull(a.getRawResult()); 185 assertFalse(a.cancel(false)); 186 assertFalse(a.cancel(true)); 187 if (a instanceof BinaryAsyncAction) 188 assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() != INITIAL_STATE); 189 190 try { 191 Thread.currentThread().interrupt(); 192 a.join(); 193 shouldThrow(); 194 } catch (Throwable expected) { 195 assertSame(t.getClass(), expected.getClass()); 196 } 197 Thread.interrupted(); 198 199 { 200 long startTime = System.nanoTime(); 201 a.quietlyJoin(); // should be no-op 202 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); 203 } 204 205 try { 206 a.get(); 207 shouldThrow(); 208 } catch (ExecutionException success) { 209 assertSame(t.getClass(), success.getCause().getClass()); 210 } catch (Throwable fail) { threadUnexpectedException(fail); } 211 212 try { 213 a.get(randomTimeout(), randomTimeUnit()); 214 shouldThrow(); 215 } catch (ExecutionException success) { 216 assertSame(t.getClass(), success.getCause().getClass()); 217 } catch (Throwable fail) { threadUnexpectedException(fail); } 218 } 219 220 public static final class FJException extends RuntimeException { 221 FJException() { super(); } 222 } 223 224 abstract static class BinaryAsyncAction extends ForkJoinTask<Void> { 225 226 private volatile BinaryAsyncAction parent; 227 228 private volatile BinaryAsyncAction sibling; 229 230 protected BinaryAsyncAction() { 231 setForkJoinTaskTag(INITIAL_STATE); 232 } 233 234 public final Void getRawResult() { return null; } 235 protected final void setRawResult(Void mustBeNull) { } 236 237 public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) { 238 x.parent = y.parent = this; 239 x.sibling = y; 240 y.sibling = x; 241 } 242 243 protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { 244 if (this.getForkJoinTaskTag() != COMPLETE_STATE || 245 x.getForkJoinTaskTag() != COMPLETE_STATE || 246 y.getForkJoinTaskTag() != COMPLETE_STATE) { 247 completeThisExceptionally(new FJException()); 248 } 249 } 250 251 protected boolean onException() { 252 return true; 253 } 254 255 public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) { 256 linkSubtasks(x, y); 257 y.fork(); 258 x.fork(); 259 } 260 261 private void completeThis() { 262 setForkJoinTaskTag(COMPLETE_STATE); 263 super.complete(null); 264 } 265 266 private void completeThisExceptionally(Throwable ex) { 267 setForkJoinTaskTag(EXCEPTION_STATE); 268 super.completeExceptionally(ex); 269 } 270 271 public boolean cancel(boolean mayInterruptIfRunning) { 272 if (super.cancel(mayInterruptIfRunning)) { 273 completeExceptionally(new FJException()); 274 return true; 275 } 276 return false; 277 } 278 279 public final void complete() { 280 BinaryAsyncAction a = this; 281 for (;;) { 282 BinaryAsyncAction s = a.sibling; 283 BinaryAsyncAction p = a.parent; 284 a.sibling = null; 285 a.parent = null; 286 a.completeThis(); 287 if (p == null || 288 p.compareAndSetForkJoinTaskTag(INITIAL_STATE, COMPLETE_STATE)) 289 break; 290 try { 291 p.onComplete(a, s); 292 } catch (Throwable rex) { 293 p.completeExceptionally(rex); 294 return; 295 } 296 a = p; 297 } 298 } 299 300 public final void completeExceptionally(Throwable ex) { 301 for (BinaryAsyncAction a = this;;) { 302 a.completeThisExceptionally(ex); 303 BinaryAsyncAction s = a.sibling; 304 if (s != null && !s.isDone()) 305 s.completeExceptionally(ex); 306 if ((a = a.parent) == null) 307 break; 308 } 309 } 310 311 public final BinaryAsyncAction getParent() { 312 return parent; 313 } 314 315 public BinaryAsyncAction getSibling() { 316 return sibling; 317 } 318 319 public void reinitialize() { 320 parent = sibling = null; 321 super.reinitialize(); 322 } 323 324 } 325 326 final class AsyncFib extends BinaryAsyncAction { 327 int number; 328 int expectedResult; 329 public AsyncFib(int number) { 330 this.number = number; 331 this.expectedResult = fib[number]; 332 } 333 334 public final boolean exec() { 335 try { 336 AsyncFib f = this; 337 int n = f.number; 338 while (n > 1) { 339 AsyncFib p = f; 340 AsyncFib r = new AsyncFib(n - 2); 341 f = new AsyncFib(--n); 342 p.linkSubtasks(r, f); 343 r.fork(); 344 } 345 f.complete(); 346 } 347 catch (Throwable ex) { 348 compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE); 349 } 350 if (getForkJoinTaskTag() == EXCEPTION_STATE) 351 throw new FJException(); 352 return false; 353 } 354 355 protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { 356 number = ((AsyncFib)x).number + ((AsyncFib)y).number; 357 super.onComplete(x, y); 358 } 359 360 public void checkCompletedNormally() { 361 assertEquals(expectedResult, number); 362 ForkJoinTask8Test.this.checkCompletedNormally(this); 363 } 364 } 365 366 static final class FailingAsyncFib extends BinaryAsyncAction { 367 int number; 368 public FailingAsyncFib(int n) { 369 this.number = n; 370 } 371 372 public final boolean exec() { 373 try { 374 FailingAsyncFib f = this; 375 int n = f.number; 376 while (n > 1) { 377 FailingAsyncFib p = f; 378 FailingAsyncFib r = new FailingAsyncFib(n - 2); 379 f = new FailingAsyncFib(--n); 380 p.linkSubtasks(r, f); 381 r.fork(); 382 } 383 f.complete(); 384 } 385 catch (Throwable ex) { 386 compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE); 387 } 388 if (getForkJoinTaskTag() == EXCEPTION_STATE) 389 throw new FJException(); 390 return false; 391 } 392 393 protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { 394 completeExceptionally(new FJException()); 395 } 396 } 397 398 /** 399 * invoke returns when task completes normally. 400 * isCompletedAbnormally and isCancelled return false for normally 401 * completed tasks; getRawResult returns null. 402 */ 403 public void testInvoke() { 404 testInvoke(mainPool()); 405 } 406 public void testInvoke_Singleton() { 407 testInvoke(singletonPool()); 408 } 409 public void testInvoke(ForkJoinPool pool) { 410 RecursiveAction a = new CheckedRecursiveAction() { 411 protected void realCompute() { 412 AsyncFib f = new AsyncFib(8); 413 assertNull(f.invoke()); 414 f.checkCompletedNormally(); 415 }}; 416 testInvokeOnPool(pool, a); 417 } 418 419 /** 420 * quietlyInvoke task returns when task completes normally. 421 * isCompletedAbnormally and isCancelled return false for normally 422 * completed tasks 423 */ 424 public void testQuietlyInvoke() { 425 testQuietlyInvoke(mainPool()); 426 } 427 public void testQuietlyInvoke_Singleton() { 428 testQuietlyInvoke(singletonPool()); 429 } 430 public void testQuietlyInvoke(ForkJoinPool pool) { 431 RecursiveAction a = new CheckedRecursiveAction() { 432 protected void realCompute() { 433 AsyncFib f = new AsyncFib(8); 434 f.quietlyInvoke(); 435 f.checkCompletedNormally(); 436 }}; 437 testInvokeOnPool(pool, a); 438 } 439 440 /** 441 * join of a forked task returns when task completes 442 */ 443 public void testForkJoin() { 444 testForkJoin(mainPool()); 445 } 446 public void testForkJoin_Singleton() { 447 testForkJoin(singletonPool()); 448 } 449 public void testForkJoin(ForkJoinPool pool) { 450 RecursiveAction a = new CheckedRecursiveAction() { 451 protected void realCompute() { 452 AsyncFib f = new AsyncFib(8); 453 assertSame(f, f.fork()); 454 assertNull(f.join()); 455 f.checkCompletedNormally(); 456 }}; 457 testInvokeOnPool(pool, a); 458 } 459 460 /** 461 * get of a forked task returns when task completes 462 */ 463 public void testForkGet() { 464 testForkGet(mainPool()); 465 } 466 public void testForkGet_Singleton() { 467 testForkGet(singletonPool()); 468 } 469 public void testForkGet(ForkJoinPool pool) { 470 RecursiveAction a = new CheckedRecursiveAction() { 471 protected void realCompute() throws Exception { 472 AsyncFib f = new AsyncFib(8); 473 assertSame(f, f.fork()); 474 assertNull(f.get()); 475 f.checkCompletedNormally(); 476 }}; 477 testInvokeOnPool(pool, a); 478 } 479 480 /** 481 * timed get of a forked task returns when task completes 482 */ 483 public void testForkTimedGet() { 484 testForkTimedGet(mainPool()); 485 } 486 public void testForkTimedGet_Singleton() { 487 testForkTimedGet(singletonPool()); 488 } 489 public void testForkTimedGet(ForkJoinPool pool) { 490 RecursiveAction a = new CheckedRecursiveAction() { 491 protected void realCompute() throws Exception { 492 AsyncFib f = new AsyncFib(8); 493 assertSame(f, f.fork()); 494 assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); 495 f.checkCompletedNormally(); 496 }}; 497 testInvokeOnPool(pool, a); 498 } 499 500 /** 501 * timed get with null time unit throws NullPointerException 502 */ 503 public void testForkTimedGetNullTimeUnit() { 504 testForkTimedGetNullTimeUnit(mainPool()); 505 } 506 public void testForkTimedGetNullTimeUnit_Singleton() { 507 testForkTimedGet(singletonPool()); 508 } 509 public void testForkTimedGetNullTimeUnit(ForkJoinPool pool) { 510 RecursiveAction a = new CheckedRecursiveAction() { 511 protected void realCompute() throws Exception { 512 AsyncFib f = new AsyncFib(8); 513 assertSame(f, f.fork()); 514 try { 515 f.get(randomTimeout(), null); 516 shouldThrow(); 517 } catch (NullPointerException success) {} 518 }}; 519 testInvokeOnPool(pool, a); 520 } 521 522 /** 523 * quietlyJoin of a forked task returns when task completes 524 */ 525 public void testForkQuietlyJoin() { 526 testForkQuietlyJoin(mainPool()); 527 } 528 public void testForkQuietlyJoin_Singleton() { 529 testForkQuietlyJoin(singletonPool()); 530 } 531 public void testForkQuietlyJoin(ForkJoinPool pool) { 532 RecursiveAction a = new CheckedRecursiveAction() { 533 protected void realCompute() { 534 AsyncFib f = new AsyncFib(8); 535 assertSame(f, f.fork()); 536 f.quietlyJoin(); 537 f.checkCompletedNormally(); 538 }}; 539 testInvokeOnPool(pool, a); 540 } 541 542 /** 543 * helpQuiesce returns when tasks are complete. 544 * getQueuedTaskCount returns 0 when quiescent 545 */ 546 public void testForkHelpQuiesce() { 547 testForkHelpQuiesce(mainPool()); 548 } 549 public void testForkHelpQuiesce_Singleton() { 550 testForkHelpQuiesce(singletonPool()); 551 } 552 public void testForkHelpQuiesce(ForkJoinPool pool) { 553 RecursiveAction a = new CheckedRecursiveAction() { 554 protected void realCompute() { 555 AsyncFib f = new AsyncFib(8); 556 assertSame(f, f.fork()); 557 helpQuiesce(); 558 assertEquals(0, getQueuedTaskCount()); 559 f.checkCompletedNormally(); 560 }}; 561 testInvokeOnPool(pool, a); 562 } 563 564 /** 565 * invoke task throws exception when task completes abnormally 566 */ 567 public void testAbnormalInvoke() { 568 testAbnormalInvoke(mainPool()); 569 } 570 public void testAbnormalInvoke_Singleton() { 571 testAbnormalInvoke(singletonPool()); 572 } 573 public void testAbnormalInvoke(ForkJoinPool pool) { 574 RecursiveAction a = new CheckedRecursiveAction() { 575 protected void realCompute() { 576 FailingAsyncFib f = new FailingAsyncFib(8); 577 try { 578 f.invoke(); 579 shouldThrow(); 580 } catch (FJException success) { 581 checkCompletedAbnormally(f, success); 582 } 583 }}; 584 testInvokeOnPool(pool, a); 585 } 586 587 /** 588 * quietlyInvoke task returns when task completes abnormally 589 */ 590 public void testAbnormalQuietlyInvoke() { 591 testAbnormalQuietlyInvoke(mainPool()); 592 } 593 public void testAbnormalQuietlyInvoke_Singleton() { 594 testAbnormalQuietlyInvoke(singletonPool()); 595 } 596 public void testAbnormalQuietlyInvoke(ForkJoinPool pool) { 597 RecursiveAction a = new CheckedRecursiveAction() { 598 protected void realCompute() { 599 FailingAsyncFib f = new FailingAsyncFib(8); 600 f.quietlyInvoke(); 601 assertTrue(f.getException() instanceof FJException); 602 checkCompletedAbnormally(f, f.getException()); 603 }}; 604 testInvokeOnPool(pool, a); 605 } 606 607 /** 608 * join of a forked task throws exception when task completes abnormally 609 */ 610 public void testAbnormalForkJoin() { 611 testAbnormalForkJoin(mainPool()); 612 } 613 public void testAbnormalForkJoin_Singleton() { 614 testAbnormalForkJoin(singletonPool()); 615 } 616 public void testAbnormalForkJoin(ForkJoinPool pool) { 617 RecursiveAction a = new CheckedRecursiveAction() { 618 protected void realCompute() { 619 FailingAsyncFib f = new FailingAsyncFib(8); 620 assertSame(f, f.fork()); 621 try { 622 f.join(); 623 shouldThrow(); 624 } catch (FJException success) { 625 checkCompletedAbnormally(f, success); 626 } 627 }}; 628 testInvokeOnPool(pool, a); 629 } 630 631 /** 632 * get of a forked task throws exception when task completes abnormally 633 */ 634 public void testAbnormalForkGet() { 635 testAbnormalForkGet(mainPool()); 636 } 637 public void testAbnormalForkGet_Singleton() { 638 testAbnormalForkJoin(singletonPool()); 639 } 640 public void testAbnormalForkGet(ForkJoinPool pool) { 641 RecursiveAction a = new CheckedRecursiveAction() { 642 protected void realCompute() throws Exception { 643 FailingAsyncFib f = new FailingAsyncFib(8); 644 assertSame(f, f.fork()); 645 try { 646 f.get(); 647 shouldThrow(); 648 } catch (ExecutionException success) { 649 Throwable cause = success.getCause(); 650 assertTrue(cause instanceof FJException); 651 checkCompletedAbnormally(f, cause); 652 } 653 }}; 654 testInvokeOnPool(pool, a); 655 } 656 657 /** 658 * timed get of a forked task throws exception when task completes abnormally 659 */ 660 public void testAbnormalForkTimedGet() { 661 testAbnormalForkTimedGet(mainPool()); 662 } 663 public void testAbnormalForkTimedGet_Singleton() { 664 testAbnormalForkTimedGet(singletonPool()); 665 } 666 public void testAbnormalForkTimedGet(ForkJoinPool pool) { 667 RecursiveAction a = new CheckedRecursiveAction() { 668 protected void realCompute() throws Exception { 669 FailingAsyncFib f = new FailingAsyncFib(8); 670 assertSame(f, f.fork()); 671 try { 672 f.get(LONG_DELAY_MS, MILLISECONDS); 673 shouldThrow(); 674 } catch (ExecutionException success) { 675 Throwable cause = success.getCause(); 676 assertTrue(cause instanceof FJException); 677 checkCompletedAbnormally(f, cause); 678 } 679 }}; 680 testInvokeOnPool(pool, a); 681 } 682 683 /** 684 * quietlyJoin of a forked task returns when task completes abnormally 685 */ 686 public void testAbnormalForkQuietlyJoin() { 687 testAbnormalForkQuietlyJoin(mainPool()); 688 } 689 public void testAbnormalForkQuietlyJoin_Singleton() { 690 testAbnormalForkQuietlyJoin(singletonPool()); 691 } 692 public void testAbnormalForkQuietlyJoin(ForkJoinPool pool) { 693 RecursiveAction a = new CheckedRecursiveAction() { 694 protected void realCompute() { 695 FailingAsyncFib f = new FailingAsyncFib(8); 696 assertSame(f, f.fork()); 697 f.quietlyJoin(); 698 assertTrue(f.getException() instanceof FJException); 699 checkCompletedAbnormally(f, f.getException()); 700 }}; 701 testInvokeOnPool(pool, a); 702 } 703 704 /** 705 * getPool of executing task returns its pool 706 */ 707 public void testGetPool() { 708 testGetPool(mainPool()); 709 } 710 public void testGetPool_Singleton() { 711 testGetPool(singletonPool()); 712 } 713 public void testGetPool(ForkJoinPool pool) { 714 RecursiveAction a = new CheckedRecursiveAction() { 715 protected void realCompute() { 716 assertSame(pool, getPool()); 717 }}; 718 testInvokeOnPool(pool, a); 719 } 720 721 /** 722 * getPool of non-FJ task returns null 723 */ 724 public void testGetPool2() { 725 RecursiveAction a = new CheckedRecursiveAction() { 726 protected void realCompute() { 727 assertNull(getPool()); 728 }}; 729 assertNull(a.invoke()); 730 } 731 732 /** 733 * inForkJoinPool of executing task returns true 734 */ 735 public void testInForkJoinPool() { 736 testInForkJoinPool(mainPool()); 737 } 738 public void testInForkJoinPool_Singleton() { 739 testInForkJoinPool(singletonPool()); 740 } 741 public void testInForkJoinPool(ForkJoinPool pool) { 742 RecursiveAction a = new CheckedRecursiveAction() { 743 protected void realCompute() { 744 assertTrue(inForkJoinPool()); 745 }}; 746 testInvokeOnPool(pool, a); 747 } 748 749 /** 750 * inForkJoinPool of non-FJ task returns false 751 */ 752 public void testInForkJoinPool2() { 753 RecursiveAction a = new CheckedRecursiveAction() { 754 protected void realCompute() { 755 assertFalse(inForkJoinPool()); 756 }}; 757 assertNull(a.invoke()); 758 } 759 760 /** 761 * setRawResult(null) succeeds 762 */ 763 public void testSetRawResult() { 764 RecursiveAction a = new CheckedRecursiveAction() { 765 protected void realCompute() { 766 setRawResult(null); 767 assertNull(getRawResult()); 768 }}; 769 assertNull(a.invoke()); 770 } 771 772 /** 773 * invoke task throws exception after invoking completeExceptionally 774 */ 775 public void testCompleteExceptionally() { 776 testCompleteExceptionally(mainPool()); 777 } 778 public void testCompleteExceptionally_Singleton() { 779 testCompleteExceptionally(singletonPool()); 780 } 781 public void testCompleteExceptionally(ForkJoinPool pool) { 782 RecursiveAction a = new CheckedRecursiveAction() { 783 protected void realCompute() { 784 AsyncFib f = new AsyncFib(8); 785 f.completeExceptionally(new FJException()); 786 try { 787 f.invoke(); 788 shouldThrow(); 789 } catch (FJException success) { 790 checkCompletedAbnormally(f, success); 791 } 792 }}; 793 testInvokeOnPool(pool, a); 794 } 795 796 /** 797 * invokeAll(tasks) with 1 argument invokes task 798 */ 799 public void testInvokeAll1() { 800 testInvokeAll1(mainPool()); 801 } 802 public void testInvokeAll1_Singleton() { 803 testInvokeAll1(singletonPool()); 804 } 805 public void testInvokeAll1(ForkJoinPool pool) { 806 RecursiveAction a = new CheckedRecursiveAction() { 807 protected void realCompute() { 808 AsyncFib f = new AsyncFib(8); 809 invokeAll(f); 810 f.checkCompletedNormally(); 811 }}; 812 testInvokeOnPool(pool, a); 813 } 814 815 /** 816 * invokeAll(t1, t2) invokes all task arguments 817 */ 818 public void testInvokeAll2() { 819 testInvokeAll2(mainPool()); 820 } 821 public void testInvokeAll2_Singleton() { 822 testInvokeAll2(singletonPool()); 823 } 824 public void testInvokeAll2(ForkJoinPool pool) { 825 RecursiveAction a = new CheckedRecursiveAction() { 826 protected void realCompute() { 827 AsyncFib[] tasks = { 828 new AsyncFib(8), 829 new AsyncFib(9), 830 }; 831 invokeAll(tasks[0], tasks[1]); 832 for (AsyncFib task : tasks) assertTrue(task.isDone()); 833 for (AsyncFib task : tasks) task.checkCompletedNormally(); 834 }}; 835 testInvokeOnPool(pool, a); 836 } 837 838 /** 839 * invokeAll(tasks) with > 2 argument invokes tasks 840 */ 841 public void testInvokeAll3() { 842 testInvokeAll3(mainPool()); 843 } 844 public void testInvokeAll3_Singleton() { 845 testInvokeAll3(singletonPool()); 846 } 847 public void testInvokeAll3(ForkJoinPool pool) { 848 RecursiveAction a = new CheckedRecursiveAction() { 849 protected void realCompute() { 850 AsyncFib[] tasks = { 851 new AsyncFib(8), 852 new AsyncFib(9), 853 new AsyncFib(7), 854 }; 855 invokeAll(tasks[0], tasks[1], tasks[2]); 856 for (AsyncFib task : tasks) assertTrue(task.isDone()); 857 for (AsyncFib task : tasks) task.checkCompletedNormally(); 858 }}; 859 testInvokeOnPool(pool, a); 860 } 861 862 /** 863 * invokeAll(collection) invokes all tasks in the collection 864 */ 865 public void testInvokeAllCollection() { 866 testInvokeAllCollection(mainPool()); 867 } 868 public void testInvokeAllCollection_Singleton() { 869 testInvokeAllCollection(singletonPool()); 870 } 871 public void testInvokeAllCollection(ForkJoinPool pool) { 872 RecursiveAction a = new CheckedRecursiveAction() { 873 protected void realCompute() { 874 AsyncFib[] tasks = { 875 new AsyncFib(8), 876 new AsyncFib(9), 877 new AsyncFib(7), 878 }; 879 invokeAll(Arrays.asList(tasks)); 880 for (AsyncFib task : tasks) assertTrue(task.isDone()); 881 for (AsyncFib task : tasks) task.checkCompletedNormally(); 882 }}; 883 testInvokeOnPool(pool, a); 884 } 885 886 /** 887 * invokeAll(tasks) with any null task throws NullPointerException 888 */ 889 public void testInvokeAllNullTask() { 890 testInvokeAllNullTask(mainPool()); 891 } 892 public void testInvokeAllNullTask_Singleton() { 893 testInvokeAllNullTask(singletonPool()); 894 } 895 public void testInvokeAllNullTask(ForkJoinPool pool) { 896 RecursiveAction a = new CheckedRecursiveAction() { 897 protected void realCompute() { 898 AsyncFib nul = null; 899 Runnable[] throwingActions = { 900 () -> invokeAll(nul), 901 () -> invokeAll(nul, nul), 902 () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul), 903 () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)), 904 () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)), 905 }; 906 assertThrows(NullPointerException.class, throwingActions); 907 }}; 908 testInvokeOnPool(pool, a); 909 } 910 911 /** 912 * invokeAll(tasks) with 1 argument throws exception if task does 913 */ 914 public void testAbnormalInvokeAll1() { 915 testAbnormalInvokeAll1(mainPool()); 916 } 917 public void testAbnormalInvokeAll1_Singleton() { 918 testAbnormalInvokeAll1(singletonPool()); 919 } 920 public void testAbnormalInvokeAll1(ForkJoinPool pool) { 921 RecursiveAction a = new CheckedRecursiveAction() { 922 protected void realCompute() { 923 FailingAsyncFib g = new FailingAsyncFib(9); 924 try { 925 invokeAll(g); 926 shouldThrow(); 927 } catch (FJException success) { 928 checkCompletedAbnormally(g, success); 929 } 930 }}; 931 testInvokeOnPool(pool, a); 932 } 933 934 /** 935 * invokeAll(t1, t2) throw exception if any task does 936 */ 937 public void testAbnormalInvokeAll2() { 938 testAbnormalInvokeAll2(mainPool()); 939 } 940 public void testAbnormalInvokeAll2_Singleton() { 941 testAbnormalInvokeAll2(singletonPool()); 942 } 943 public void testAbnormalInvokeAll2(ForkJoinPool pool) { 944 RecursiveAction a = new CheckedRecursiveAction() { 945 protected void realCompute() { 946 AsyncFib f = new AsyncFib(8); 947 FailingAsyncFib g = new FailingAsyncFib(9); 948 ForkJoinTask[] tasks = { f, g }; 949 shuffle(tasks); 950 try { 951 invokeAll(tasks[0], tasks[1]); 952 shouldThrow(); 953 } catch (FJException success) { 954 checkCompletedAbnormally(g, success); 955 } 956 }}; 957 testInvokeOnPool(pool, a); 958 } 959 960 /** 961 * invokeAll(tasks) with > 2 argument throws exception if any task does 962 */ 963 public void testAbnormalInvokeAll3() { 964 testAbnormalInvokeAll3(mainPool()); 965 } 966 public void testAbnormalInvokeAll3_Singleton() { 967 testAbnormalInvokeAll3(singletonPool()); 968 } 969 public void testAbnormalInvokeAll3(ForkJoinPool pool) { 970 RecursiveAction a = new CheckedRecursiveAction() { 971 protected void realCompute() { 972 AsyncFib f = new AsyncFib(8); 973 FailingAsyncFib g = new FailingAsyncFib(9); 974 AsyncFib h = new AsyncFib(7); 975 ForkJoinTask[] tasks = { f, g, h }; 976 shuffle(tasks); 977 try { 978 invokeAll(tasks[0], tasks[1], tasks[2]); 979 shouldThrow(); 980 } catch (FJException success) { 981 checkCompletedAbnormally(g, success); 982 } 983 }}; 984 testInvokeOnPool(pool, a); 985 } 986 987 /** 988 * invokeAll(collection) throws exception if any task does 989 */ 990 public void testAbnormalInvokeAllCollection() { 991 testAbnormalInvokeAllCollection(mainPool()); 992 } 993 public void testAbnormalInvokeAllCollection_Singleton() { 994 testAbnormalInvokeAllCollection(singletonPool()); 995 } 996 public void testAbnormalInvokeAllCollection(ForkJoinPool pool) { 997 RecursiveAction a = new CheckedRecursiveAction() { 998 protected void realCompute() { 999 FailingAsyncFib f = new FailingAsyncFib(8); 1000 AsyncFib g = new AsyncFib(9); 1001 AsyncFib h = new AsyncFib(7); 1002 ForkJoinTask[] tasks = { f, g, h }; 1003 shuffle(tasks); 1004 try { 1005 invokeAll(Arrays.asList(tasks)); 1006 shouldThrow(); 1007 } catch (FJException success) { 1008 checkCompletedAbnormally(f, success); 1009 } 1010 }}; 1011 testInvokeOnPool(pool, a); 1012 } 1013 1014 /** 1015 * tryUnfork returns true for most recent unexecuted task, 1016 * and suppresses execution 1017 */ 1018 public void testTryUnfork() { 1019 RecursiveAction a = new CheckedRecursiveAction() { 1020 protected void realCompute() { 1021 AsyncFib g = new AsyncFib(9); 1022 assertSame(g, g.fork()); 1023 AsyncFib f = new AsyncFib(8); 1024 assertSame(f, f.fork()); 1025 assertTrue(f.tryUnfork()); 1026 helpQuiesce(); 1027 checkNotDone(f); 1028 g.checkCompletedNormally(); 1029 }}; 1030 testInvokeOnPool(singletonPool(), a); 1031 } 1032 1033 /** 1034 * getSurplusQueuedTaskCount returns > 0 when 1035 * there are more tasks than threads 1036 */ 1037 public void testGetSurplusQueuedTaskCount() { 1038 RecursiveAction a = new CheckedRecursiveAction() { 1039 protected void realCompute() { 1040 AsyncFib h = new AsyncFib(7); 1041 assertSame(h, h.fork()); 1042 AsyncFib g = new AsyncFib(9); 1043 assertSame(g, g.fork()); 1044 AsyncFib f = new AsyncFib(8); 1045 assertSame(f, f.fork()); 1046 assertTrue(getSurplusQueuedTaskCount() > 0); 1047 helpQuiesce(); 1048 assertEquals(0, getSurplusQueuedTaskCount()); 1049 f.checkCompletedNormally(); 1050 g.checkCompletedNormally(); 1051 h.checkCompletedNormally(); 1052 }}; 1053 testInvokeOnPool(singletonPool(), a); 1054 } 1055 1056 /** 1057 * peekNextLocalTask returns most recent unexecuted task. 1058 */ 1059 public void testPeekNextLocalTask() { 1060 RecursiveAction a = new CheckedRecursiveAction() { 1061 protected void realCompute() { 1062 AsyncFib g = new AsyncFib(9); 1063 assertSame(g, g.fork()); 1064 AsyncFib f = new AsyncFib(8); 1065 assertSame(f, f.fork()); 1066 assertSame(f, peekNextLocalTask()); 1067 assertNull(f.join()); 1068 f.checkCompletedNormally(); 1069 helpQuiesce(); 1070 g.checkCompletedNormally(); 1071 }}; 1072 testInvokeOnPool(singletonPool(), a); 1073 } 1074 1075 /** 1076 * pollNextLocalTask returns most recent unexecuted task without 1077 * executing it 1078 */ 1079 public void testPollNextLocalTask() { 1080 RecursiveAction a = new CheckedRecursiveAction() { 1081 protected void realCompute() { 1082 AsyncFib g = new AsyncFib(9); 1083 assertSame(g, g.fork()); 1084 AsyncFib f = new AsyncFib(8); 1085 assertSame(f, f.fork()); 1086 assertSame(f, pollNextLocalTask()); 1087 helpQuiesce(); 1088 checkNotDone(f); 1089 g.checkCompletedNormally(); 1090 }}; 1091 testInvokeOnPool(singletonPool(), a); 1092 } 1093 1094 /** 1095 * pollTask returns an unexecuted task without executing it 1096 */ 1097 public void testPollTask() { 1098 RecursiveAction a = new CheckedRecursiveAction() { 1099 protected void realCompute() { 1100 AsyncFib g = new AsyncFib(9); 1101 assertSame(g, g.fork()); 1102 AsyncFib f = new AsyncFib(8); 1103 assertSame(f, f.fork()); 1104 assertSame(f, pollTask()); 1105 helpQuiesce(); 1106 checkNotDone(f); 1107 g.checkCompletedNormally(); 1108 }}; 1109 testInvokeOnPool(singletonPool(), a); 1110 } 1111 1112 /** 1113 * peekNextLocalTask returns least recent unexecuted task in async mode 1114 */ 1115 public void testPeekNextLocalTaskAsync() { 1116 RecursiveAction a = new CheckedRecursiveAction() { 1117 protected void realCompute() { 1118 AsyncFib g = new AsyncFib(9); 1119 assertSame(g, g.fork()); 1120 AsyncFib f = new AsyncFib(8); 1121 assertSame(f, f.fork()); 1122 assertSame(g, peekNextLocalTask()); 1123 assertNull(f.join()); 1124 helpQuiesce(); 1125 f.checkCompletedNormally(); 1126 g.checkCompletedNormally(); 1127 }}; 1128 testInvokeOnPool(asyncSingletonPool(), a); 1129 } 1130 1131 /** 1132 * pollNextLocalTask returns least recent unexecuted task without 1133 * executing it, in async mode 1134 */ 1135 public void testPollNextLocalTaskAsync() { 1136 RecursiveAction a = new CheckedRecursiveAction() { 1137 protected void realCompute() { 1138 AsyncFib g = new AsyncFib(9); 1139 assertSame(g, g.fork()); 1140 AsyncFib f = new AsyncFib(8); 1141 assertSame(f, f.fork()); 1142 assertSame(g, pollNextLocalTask()); 1143 helpQuiesce(); 1144 f.checkCompletedNormally(); 1145 checkNotDone(g); 1146 }}; 1147 testInvokeOnPool(asyncSingletonPool(), a); 1148 } 1149 1150 /** 1151 * pollTask returns an unexecuted task without executing it, in 1152 * async mode 1153 */ 1154 public void testPollTaskAsync() { 1155 RecursiveAction a = new CheckedRecursiveAction() { 1156 protected void realCompute() { 1157 AsyncFib g = new AsyncFib(9); 1158 assertSame(g, g.fork()); 1159 AsyncFib f = new AsyncFib(8); 1160 assertSame(f, f.fork()); 1161 assertSame(g, pollTask()); 1162 helpQuiesce(); 1163 f.checkCompletedNormally(); 1164 checkNotDone(g); 1165 }}; 1166 testInvokeOnPool(asyncSingletonPool(), a); 1167 } 1168 1169 /** 1170 * ForkJoinTask.quietlyComplete returns when task completes 1171 * normally without setting a value. The most recent value 1172 * established by setRawResult(V) (or null by default) is returned 1173 * from invoke. 1174 */ 1175 public void testQuietlyComplete() { 1176 RecursiveAction a = new CheckedRecursiveAction() { 1177 protected void realCompute() { 1178 AsyncFib f = new AsyncFib(8); 1179 f.quietlyComplete(); 1180 assertEquals(8, f.number); 1181 assertTrue(f.isDone()); 1182 assertFalse(f.isCancelled()); 1183 assertTrue(f.isCompletedNormally()); 1184 assertFalse(f.isCompletedAbnormally()); 1185 assertNull(f.getException()); 1186 }}; 1187 testInvokeOnPool(mainPool(), a); 1188 } 1189 1190 // jdk9 1191 1192 /** 1193 * pollSubmission returns unexecuted submitted task, if present 1194 */ 1195 public void testPollSubmission() { 1196 final CountDownLatch done = new CountDownLatch(1); 1197 final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done)); 1198 final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done)); 1199 final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done)); 1200 final ForkJoinPool p = singletonPool(); 1201 try (PoolCleaner cleaner = cleaner(p, done)) { 1202 Thread external = new Thread(new CheckedRunnable() { 1203 public void realRun() { 1204 p.execute(a); 1205 p.execute(b); 1206 p.execute(c); 1207 }}); 1208 RecursiveAction s = new CheckedRecursiveAction() { 1209 protected void realCompute() { 1210 external.start(); 1211 try { 1212 external.join(); 1213 } catch (Exception ex) { 1214 threadUnexpectedException(ex); 1215 } 1216 assertTrue(p.hasQueuedSubmissions()); 1217 assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread); 1218 ForkJoinTask r = ForkJoinTask.pollSubmission(); 1219 assertTrue(r == a || r == b || r == c); 1220 assertFalse(r.isDone()); 1221 }}; 1222 p.invoke(s); 1223 } 1224 } 1225 1226 }