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