ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.10
Committed: Wed Aug 11 19:50:02 2010 UTC (13 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.9: +3 -111 lines
Log Message:
Sync with API simplifications

File Contents

# Content
1 /*
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/licenses/publicdomain
5 */
6 import junit.framework.*;
7 import java.util.concurrent.*;
8 import java.util.*;
9
10
11 public class RecursiveActionTest extends JSR166TestCase {
12
13 public static void main(String[] args) {
14 junit.textui.TestRunner.run (suite());
15 }
16 public static Test suite() {
17 return new TestSuite(RecursiveActionTest.class);
18 }
19
20 static final ForkJoinPool mainPool = new ForkJoinPool();
21 static final ForkJoinPool singletonPool = new ForkJoinPool(1);
22 static final ForkJoinPool asyncSingletonPool =
23 new ForkJoinPool(1, ForkJoinPool.defaultForkJoinWorkerThreadFactory,
24 null, true);
25
26 static final class FJException extends RuntimeException {
27 FJException() { super(); }
28 }
29
30 // A simple recursive action for testing
31 static final class FibAction extends RecursiveAction {
32 final int number;
33 int result;
34 FibAction(int n) { number = n; }
35 public void compute() {
36 int n = number;
37 if (n <= 1)
38 result = n;
39 else {
40 FibAction f1 = new FibAction(n - 1);
41 FibAction f2 = new FibAction(n - 2);
42 invokeAll(f1, f2);
43 result = f1.result + f2.result;
44 }
45 }
46 }
47
48 // A recursive action failing in base case
49 static final class FailingFibAction extends RecursiveAction {
50 final int number;
51 int result;
52 FailingFibAction(int n) { number = n; }
53 public void compute() {
54 int n = number;
55 if (n <= 1)
56 throw new FJException();
57 else {
58 FailingFibAction f1 = new FailingFibAction(n - 1);
59 FailingFibAction f2 = new FailingFibAction(n - 2);
60 invokeAll(f1, f2);
61 result = f1.result + f2.result;
62 }
63 }
64 }
65
66 /**
67 * invoke returns when task completes normally.
68 * isCompletedAbnormally and isCancelled return false for normally
69 * completed tasks. getRawResult of a RecursiveAction returns null;
70 *
71 */
72 public void testInvoke() {
73 RecursiveAction a = new RecursiveAction() {
74 public void compute() {
75 FibAction f = new FibAction(8);
76 f.invoke();
77 threadAssertTrue(f.result == 21);
78 threadAssertTrue(f.isDone());
79 threadAssertFalse(f.isCancelled());
80 threadAssertFalse(f.isCompletedAbnormally());
81 threadAssertTrue(f.getRawResult() == null);
82 }};
83 mainPool.invoke(a);
84 }
85
86 /**
87 * quietlyInvoke task returns when task completes normally.
88 * isCompletedAbnormally and isCancelled return false for normally
89 * completed tasks
90 */
91 public void testQuietlyInvoke() {
92 RecursiveAction a = new RecursiveAction() {
93 public void compute() {
94 FibAction f = new FibAction(8);
95 f.quietlyInvoke();
96 threadAssertTrue(f.result == 21);
97 threadAssertTrue(f.isDone());
98 threadAssertFalse(f.isCancelled());
99 threadAssertFalse(f.isCompletedAbnormally());
100 threadAssertTrue(f.getRawResult() == null);
101 }};
102 mainPool.invoke(a);
103 }
104
105 /**
106 * join of a forked task returns when task completes
107 */
108 public void testForkJoin() {
109 RecursiveAction a = new RecursiveAction() {
110 public void compute() {
111 FibAction f = new FibAction(8);
112 f.fork();
113 f.join();
114 threadAssertTrue(f.result == 21);
115 threadAssertTrue(f.isDone());
116 threadAssertTrue(f.getRawResult() == null);
117 }};
118 mainPool.invoke(a);
119 }
120
121 /**
122 * get of a forked task returns when task completes
123 */
124 public void testForkGet() {
125 RecursiveAction a = new RecursiveAction() {
126 public void compute() {
127 try {
128 FibAction f = new FibAction(8);
129 f.fork();
130 f.get();
131 threadAssertTrue(f.result == 21);
132 threadAssertTrue(f.isDone());
133 } catch (Exception ex) {
134 unexpectedException(ex);
135 }
136 }};
137 mainPool.invoke(a);
138 }
139
140 /**
141 * timed get of a forked task returns when task completes
142 */
143 public void testForkTimedGet() {
144 RecursiveAction a = new RecursiveAction() {
145 public void compute() {
146 try {
147 FibAction f = new FibAction(8);
148 f.fork();
149 f.get(5L, TimeUnit.SECONDS);
150 threadAssertTrue(f.result == 21);
151 threadAssertTrue(f.isDone());
152 } catch (Exception ex) {
153 unexpectedException(ex);
154 }
155 }};
156 mainPool.invoke(a);
157 }
158
159 /**
160 * timed get with null time unit throws NPE
161 */
162 public void testForkTimedGetNPE() {
163 RecursiveAction a = new RecursiveAction() {
164 public void compute() {
165 try {
166 FibAction f = new FibAction(8);
167 f.fork();
168 f.get(5L, null);
169 shouldThrow();
170 } catch (NullPointerException success) {
171 } catch (Exception ex) {
172 unexpectedException(ex);
173 }
174 }};
175 mainPool.invoke(a);
176 }
177
178 /**
179 * quietlyJoin of a forked task returns when task completes
180 */
181 public void testForkQuietlyJoin() {
182 RecursiveAction a = new RecursiveAction() {
183 public void compute() {
184 FibAction f = new FibAction(8);
185 f.fork();
186 f.quietlyJoin();
187 threadAssertTrue(f.result == 21);
188 threadAssertTrue(f.isDone());
189 }};
190 mainPool.invoke(a);
191 }
192
193
194 /**
195 * helpQuiesce returns when tasks are complete.
196 * getQueuedTaskCount returns 0 when quiescent
197 */
198 public void testForkHelpQuiesce() {
199 RecursiveAction a = new RecursiveAction() {
200 public void compute() {
201 FibAction f = new FibAction(8);
202 f.fork();
203 f.helpQuiesce();
204 threadAssertTrue(f.result == 21);
205 threadAssertTrue(f.isDone());
206 threadAssertTrue(getQueuedTaskCount() == 0);
207 }};
208 mainPool.invoke(a);
209 }
210
211
212 /**
213 * invoke task throws exception when task completes abnormally
214 */
215 public void testAbnormalInvoke() {
216 RecursiveAction a = new RecursiveAction() {
217 public void compute() {
218 try {
219 FailingFibAction f = new FailingFibAction(8);
220 f.invoke();
221 shouldThrow();
222 } catch (FJException success) {
223 }
224 }};
225 mainPool.invoke(a);
226 }
227
228 /**
229 * quietlyInvoke task returns when task completes abnormally
230 */
231 public void testAbnormalQuietlyInvoke() {
232 RecursiveAction a = new RecursiveAction() {
233 public void compute() {
234 FailingFibAction f = new FailingFibAction(8);
235 f.quietlyInvoke();
236 threadAssertTrue(f.isDone());
237 }};
238 mainPool.invoke(a);
239 }
240
241 /**
242 * join of a forked task throws exception when task completes abnormally
243 */
244 public void testAbnormalForkJoin() {
245 RecursiveAction a = new RecursiveAction() {
246 public void compute() {
247 try {
248 FailingFibAction f = new FailingFibAction(8);
249 f.fork();
250 f.join();
251 shouldThrow();
252 } catch (FJException success) {
253 }
254 }};
255 mainPool.invoke(a);
256 }
257
258 /**
259 * get of a forked task throws exception when task completes abnormally
260 */
261 public void testAbnormalForkGet() {
262 RecursiveAction a = new RecursiveAction() {
263 public void compute() {
264 try {
265 FailingFibAction f = new FailingFibAction(8);
266 f.fork();
267 f.get();
268 shouldThrow();
269 } catch (ExecutionException success) {
270 } catch (Exception ex) {
271 unexpectedException(ex);
272 }
273 }};
274 mainPool.invoke(a);
275 }
276
277 /**
278 * timed get of a forked task throws exception when task completes abnormally
279 */
280 public void testAbnormalForkTimedGet() {
281 RecursiveAction a = new RecursiveAction() {
282 public void compute() {
283 try {
284 FailingFibAction f = new FailingFibAction(8);
285 f.fork();
286 f.get(5L, TimeUnit.SECONDS);
287 shouldThrow();
288 } catch (ExecutionException success) {
289 } catch (Exception ex) {
290 unexpectedException(ex);
291 }
292 }};
293 mainPool.invoke(a);
294 }
295
296 /**
297 * quietlyJoin of a forked task returns when task completes abnormally
298 */
299 public void testAbnormalForkQuietlyJoin() {
300 RecursiveAction a = new RecursiveAction() {
301 public void compute() {
302 FailingFibAction f = new FailingFibAction(8);
303 f.fork();
304 f.quietlyJoin();
305 threadAssertTrue(f.isDone());
306 threadAssertTrue(f.isCompletedAbnormally());
307 threadAssertTrue(f.getException() instanceof FJException);
308 }};
309 mainPool.invoke(a);
310 }
311
312 /**
313 * invoke task throws exception when task cancelled
314 */
315 public void testCancelledInvoke() {
316 RecursiveAction a = new RecursiveAction() {
317 public void compute() {
318 try {
319 FibAction f = new FibAction(8);
320 f.cancel(true);
321 f.invoke();
322 shouldThrow();
323 } catch (CancellationException success) {
324 }
325 }};
326 mainPool.invoke(a);
327 }
328
329 /**
330 * join of a forked task throws exception when task cancelled
331 */
332 public void testCancelledForkJoin() {
333 RecursiveAction a = new RecursiveAction() {
334 public void compute() {
335 try {
336 FibAction f = new FibAction(8);
337 f.cancel(true);
338 f.fork();
339 f.join();
340 shouldThrow();
341 } catch (CancellationException success) {
342 }
343 }};
344 mainPool.invoke(a);
345 }
346
347 /**
348 * get of a forked task throws exception when task cancelled
349 */
350 public void testCancelledForkGet() {
351 RecursiveAction a = new RecursiveAction() {
352 public void compute() {
353 try {
354 FibAction f = new FibAction(8);
355 f.cancel(true);
356 f.fork();
357 f.get();
358 shouldThrow();
359 } catch (CancellationException success) {
360 } catch (Exception ex) {
361 unexpectedException(ex);
362 }
363 }};
364 mainPool.invoke(a);
365 }
366
367 /**
368 * timed get of a forked task throws exception when task cancelled
369 */
370 public void testCancelledForkTimedGet() {
371 RecursiveAction a = new RecursiveAction() {
372 public void compute() {
373 try {
374 FibAction f = new FibAction(8);
375 f.cancel(true);
376 f.fork();
377 f.get(5L, TimeUnit.SECONDS);
378 shouldThrow();
379 } catch (CancellationException success) {
380 } catch (Exception ex) {
381 unexpectedException(ex);
382 }
383 }};
384 mainPool.invoke(a);
385 }
386
387 /**
388 * quietlyJoin of a forked task returns when task cancelled
389 */
390 public void testCancelledForkQuietlyJoin() {
391 RecursiveAction a = new RecursiveAction() {
392 public void compute() {
393 FibAction f = new FibAction(8);
394 f.cancel(true);
395 f.fork();
396 f.quietlyJoin();
397 threadAssertTrue(f.isDone());
398 threadAssertTrue(f.isCompletedAbnormally());
399 threadAssertTrue(f.getException() instanceof CancellationException);
400 }};
401 mainPool.invoke(a);
402 }
403
404 /**
405 * getPool of executing task returns its pool
406 */
407 public void testGetPool() {
408 RecursiveAction a = new RecursiveAction() {
409 public void compute() {
410 threadAssertTrue(getPool() == mainPool);
411 }};
412 mainPool.invoke(a);
413 }
414
415 /**
416 * getPool of non-FJ task returns null
417 */
418 public void testGetPool2() {
419 RecursiveAction a = new RecursiveAction() {
420 public void compute() {
421 threadAssertTrue(getPool() == null);
422 }};
423 a.invoke();
424 }
425
426 /**
427 * inForkJoinPool of executing task returns true
428 */
429 public void testInForkJoinPool() {
430 RecursiveAction a = new RecursiveAction() {
431 public void compute() {
432 threadAssertTrue(inForkJoinPool());
433 }};
434 mainPool.invoke(a);
435 }
436
437 /**
438 * inForkJoinPool of non-FJ task returns false
439 */
440 public void testInForkJoinPool2() {
441 RecursiveAction a = new RecursiveAction() {
442 public void compute() {
443 threadAssertTrue(!inForkJoinPool());
444 }};
445 a.invoke();
446 }
447
448 /**
449 * getPool of current thread in pool returns its pool
450 */
451 public void testWorkerGetPool() {
452 RecursiveAction a = new RecursiveAction() {
453 public void compute() {
454 ForkJoinWorkerThread w =
455 (ForkJoinWorkerThread)(Thread.currentThread());
456 threadAssertTrue(w.getPool() == mainPool);
457 }};
458 mainPool.invoke(a);
459 }
460
461 /**
462 * getPoolIndex of current thread in pool returns 0 <= value < poolSize
463 *
464 */
465 public void testWorkerGetPoolIndex() {
466 RecursiveAction a = new RecursiveAction() {
467 public void compute() {
468 ForkJoinWorkerThread w =
469 (ForkJoinWorkerThread)(Thread.currentThread());
470 int idx = w.getPoolIndex();
471 threadAssertTrue(idx >= 0);
472 threadAssertTrue(idx < mainPool.getPoolSize());
473 }};
474 mainPool.invoke(a);
475 }
476
477
478 /**
479 * setRawResult(null) succeeds
480 */
481 public void testSetRawResult() {
482 RecursiveAction a = new RecursiveAction() {
483 public void compute() {
484 setRawResult(null);
485 }};
486 a.invoke();
487 }
488
489 /**
490 * A reinitialized task may be re-invoked
491 */
492 public void testReinitialize() {
493 RecursiveAction a = new RecursiveAction() {
494 public void compute() {
495 FibAction f = new FibAction(8);
496 f.invoke();
497 threadAssertTrue(f.result == 21);
498 threadAssertTrue(f.isDone());
499 threadAssertFalse(f.isCancelled());
500 threadAssertFalse(f.isCompletedAbnormally());
501 f.reinitialize();
502 f.invoke();
503 threadAssertTrue(f.result == 21);
504 }};
505 mainPool.invoke(a);
506 }
507
508 /**
509 * invoke task throws exception after invoking completeExceptionally
510 */
511 public void testCompleteExceptionally() {
512 RecursiveAction a = new RecursiveAction() {
513 public void compute() {
514 try {
515 FibAction f = new FibAction(8);
516 f.completeExceptionally(new FJException());
517 f.invoke();
518 shouldThrow();
519 } catch (FJException success) {
520 }
521 }};
522 mainPool.invoke(a);
523 }
524
525 /**
526 * invoke task suppresses execution invoking complete
527 */
528 public void testComplete() {
529 RecursiveAction a = new RecursiveAction() {
530 public void compute() {
531 FibAction f = new FibAction(8);
532 f.complete(null);
533 f.invoke();
534 threadAssertTrue(f.isDone());
535 threadAssertTrue(f.result == 0);
536 }};
537 mainPool.invoke(a);
538 }
539
540 /**
541 * invokeAll(t1, t2) invokes all task arguments
542 */
543 public void testInvokeAll2() {
544 RecursiveAction a = new RecursiveAction() {
545 public void compute() {
546 FibAction f = new FibAction(8);
547 FibAction g = new FibAction(9);
548 invokeAll(f, g);
549 threadAssertTrue(f.isDone());
550 threadAssertTrue(f.result == 21);
551 threadAssertTrue(g.isDone());
552 threadAssertTrue(g.result == 34);
553 }};
554 mainPool.invoke(a);
555 }
556
557 /**
558 * invokeAll(tasks) with 1 argument invokes task
559 */
560 public void testInvokeAll1() {
561 RecursiveAction a = new RecursiveAction() {
562 public void compute() {
563 FibAction f = new FibAction(8);
564 invokeAll(f);
565 threadAssertTrue(f.isDone());
566 threadAssertTrue(f.result == 21);
567 }};
568 mainPool.invoke(a);
569 }
570
571 /**
572 * invokeAll(tasks) with > 2 argument invokes tasks
573 */
574 public void testInvokeAll3() {
575 RecursiveAction a = new RecursiveAction() {
576 public void compute() {
577 FibAction f = new FibAction(8);
578 FibAction g = new FibAction(9);
579 FibAction h = new FibAction(7);
580 invokeAll(f, g, h);
581 threadAssertTrue(f.isDone());
582 threadAssertTrue(f.result == 21);
583 threadAssertTrue(g.isDone());
584 threadAssertTrue(g.result == 34);
585 threadAssertTrue(h.isDone());
586 threadAssertTrue(h.result == 13);
587 }};
588 mainPool.invoke(a);
589 }
590
591 /**
592 * invokeAll(collection) invokes all tasks in the collection
593 */
594 public void testInvokeAllCollection() {
595 RecursiveAction a = new RecursiveAction() {
596 public void compute() {
597 FibAction f = new FibAction(8);
598 FibAction g = new FibAction(9);
599 FibAction h = new FibAction(7);
600 HashSet set = new HashSet();
601 set.add(f);
602 set.add(g);
603 set.add(h);
604 invokeAll(set);
605 threadAssertTrue(f.isDone());
606 threadAssertTrue(f.result == 21);
607 threadAssertTrue(g.isDone());
608 threadAssertTrue(g.result == 34);
609 threadAssertTrue(h.isDone());
610 threadAssertTrue(h.result == 13);
611 }};
612 mainPool.invoke(a);
613 }
614
615
616 /**
617 * invokeAll(tasks) with any null task throws NPE
618 */
619 public void testInvokeAllNPE() {
620 RecursiveAction a = new RecursiveAction() {
621 public void compute() {
622 try {
623 FibAction f = new FibAction(8);
624 FibAction g = new FibAction(9);
625 FibAction h = null;
626 invokeAll(f, g, h);
627 shouldThrow();
628 } catch (NullPointerException success) {
629 }
630 }};
631 mainPool.invoke(a);
632 }
633
634 /**
635 * invokeAll(t1, t2) throw exception if any task does
636 */
637 public void testAbnormalInvokeAll2() {
638 RecursiveAction a = new RecursiveAction() {
639 public void compute() {
640 try {
641 FibAction f = new FibAction(8);
642 FailingFibAction g = new FailingFibAction(9);
643 invokeAll(f, g);
644 shouldThrow();
645 } catch (FJException success) {
646 }
647 }};
648 mainPool.invoke(a);
649 }
650
651 /**
652 * invokeAll(tasks) with 1 argument throws exception if task does
653 */
654 public void testAbnormalInvokeAll1() {
655 RecursiveAction a = new RecursiveAction() {
656 public void compute() {
657 try {
658 FailingFibAction g = new FailingFibAction(9);
659 invokeAll(g);
660 shouldThrow();
661 } catch (FJException success) {
662 }
663 }};
664 mainPool.invoke(a);
665 }
666
667 /**
668 * invokeAll(tasks) with > 2 argument throws exception if any task does
669 */
670 public void testAbnormalInvokeAll3() {
671 RecursiveAction a = new RecursiveAction() {
672 public void compute() {
673 try {
674 FibAction f = new FibAction(8);
675 FailingFibAction g = new FailingFibAction(9);
676 FibAction h = new FibAction(7);
677 invokeAll(f, g, h);
678 shouldThrow();
679 } catch (FJException success) {
680 }
681 }};
682 mainPool.invoke(a);
683 }
684
685 /**
686 * invokeAll(collection) throws exception if any task does
687 */
688 public void testAbnormalInvokeAllCollection() {
689 RecursiveAction a = new RecursiveAction() {
690 public void compute() {
691 try {
692 FailingFibAction f = new FailingFibAction(8);
693 FibAction g = new FibAction(9);
694 FibAction h = new FibAction(7);
695 HashSet set = new HashSet();
696 set.add(f);
697 set.add(g);
698 set.add(h);
699 invokeAll(set);
700 shouldThrow();
701 } catch (FJException success) {
702 }
703 }};
704 mainPool.invoke(a);
705 }
706
707 /**
708 * tryUnfork returns true for most recent unexecuted task,
709 * and suppresses execution
710 */
711 public void testTryUnfork() {
712 RecursiveAction a = new RecursiveAction() {
713 public void compute() {
714 FibAction g = new FibAction(9);
715 g.fork();
716 FibAction f = new FibAction(8);
717 f.fork();
718 threadAssertTrue(f.tryUnfork());
719 helpQuiesce();
720 threadAssertFalse(f.isDone());
721 threadAssertTrue(g.isDone());
722 }};
723 singletonPool.invoke(a);
724 }
725
726 /**
727 * getSurplusQueuedTaskCount returns > 0 when
728 * there are more tasks than threads
729 */
730 public void testGetSurplusQueuedTaskCount() {
731 RecursiveAction a = new RecursiveAction() {
732 public void compute() {
733 FibAction h = new FibAction(7);
734 h.fork();
735 FibAction g = new FibAction(9);
736 g.fork();
737 FibAction f = new FibAction(8);
738 f.fork();
739 threadAssertTrue(getSurplusQueuedTaskCount() > 0);
740 helpQuiesce();
741 }};
742 singletonPool.invoke(a);
743 }
744
745 /**
746 * peekNextLocalTask returns most recent unexecuted task.
747 */
748 public void testPeekNextLocalTask() {
749 RecursiveAction a = new RecursiveAction() {
750 public void compute() {
751 FibAction g = new FibAction(9);
752 g.fork();
753 FibAction f = new FibAction(8);
754 f.fork();
755 threadAssertTrue(peekNextLocalTask() == f);
756 f.join();
757 threadAssertTrue(f.isDone());
758 helpQuiesce();
759 }};
760 singletonPool.invoke(a);
761 }
762
763 /**
764 * pollNextLocalTask returns most recent unexecuted task
765 * without executing it
766 */
767 public void testPollNextLocalTask() {
768 RecursiveAction a = new RecursiveAction() {
769 public void compute() {
770 FibAction g = new FibAction(9);
771 g.fork();
772 FibAction f = new FibAction(8);
773 f.fork();
774 threadAssertTrue(pollNextLocalTask() == f);
775 helpQuiesce();
776 threadAssertFalse(f.isDone());
777 }};
778 singletonPool.invoke(a);
779 }
780
781 /**
782 * pollTask returns an unexecuted task
783 * without executing it
784 */
785 public void testPollTask() {
786 RecursiveAction a = new RecursiveAction() {
787 public void compute() {
788 FibAction g = new FibAction(9);
789 g.fork();
790 FibAction f = new FibAction(8);
791 f.fork();
792 threadAssertTrue(pollTask() == f);
793 helpQuiesce();
794 threadAssertFalse(f.isDone());
795 threadAssertTrue(g.isDone());
796 }};
797 singletonPool.invoke(a);
798 }
799
800 /**
801 * peekNextLocalTask returns least recent unexecuted task in async mode
802 */
803 public void testPeekNextLocalTaskAsync() {
804 RecursiveAction a = new RecursiveAction() {
805 public void compute() {
806 FibAction g = new FibAction(9);
807 g.fork();
808 FibAction f = new FibAction(8);
809 f.fork();
810 threadAssertTrue(peekNextLocalTask() == g);
811 f.join();
812 helpQuiesce();
813 threadAssertTrue(f.isDone());
814 }};
815 asyncSingletonPool.invoke(a);
816 }
817
818 /**
819 * pollNextLocalTask returns least recent unexecuted task
820 * without executing it, in async mode
821 */
822 public void testPollNextLocalTaskAsync() {
823 RecursiveAction a = new RecursiveAction() {
824 public void compute() {
825 FibAction g = new FibAction(9);
826 g.fork();
827 FibAction f = new FibAction(8);
828 f.fork();
829 threadAssertTrue(pollNextLocalTask() == g);
830 helpQuiesce();
831 threadAssertTrue(f.isDone());
832 threadAssertFalse(g.isDone());
833 }};
834 asyncSingletonPool.invoke(a);
835 }
836
837 /**
838 * pollTask returns an unexecuted task
839 * without executing it, in async mode
840 */
841 public void testPollTaskAsync() {
842 RecursiveAction a = new RecursiveAction() {
843 public void compute() {
844 FibAction g = new FibAction(9);
845 g.fork();
846 FibAction f = new FibAction(8);
847 f.fork();
848 threadAssertTrue(pollTask() == g);
849 helpQuiesce();
850 threadAssertTrue(f.isDone());
851 threadAssertFalse(g.isDone());
852 }};
853 asyncSingletonPool.invoke(a);
854 }
855
856 }