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