@@ -273,6 +273,8 @@ final boolean casNext(Aux c, Aux v) { // used only in cancellation
273
273
static final int ABNORMAL = 1 << 16 ;
274
274
static final int THROWN = 1 << 17 ;
275
275
static final int HAVE_EXCEPTION = DONE | ABNORMAL | THROWN ;
276
+ static final int NUH_BIT = 24 ; // no external caller helping
277
+ static final int NO_USER_HELP = 1 << NUH_BIT ;
276
278
static final int MARKER = 1 << 30 ; // utility marker
277
279
static final int SMASK = 0xffff ; // short bits for tags
278
280
static final int UNCOMPENSATE = 1 << 16 ; // helpJoin sentinel
@@ -292,6 +294,12 @@ private int getAndBitwiseOrStatus(int v) {
292
294
private boolean casStatus (int c , int v ) {
293
295
return U .compareAndSetInt (this , STATUS , c , v );
294
296
}
297
+ final int noUserHelp () { // nonvolatile read; return 0 or 1
298
+ return (U .getInt (this , STATUS ) & NO_USER_HELP ) >>> NUH_BIT ;
299
+ }
300
+ final void setNoUserHelp () { // for use in constructors only
301
+ U .putInt (this , STATUS , NO_USER_HELP );
302
+ }
295
303
296
304
// Support for waiting and signalling
297
305
@@ -330,14 +338,9 @@ private void setDone() {
330
338
*/
331
339
final int trySetCancelled () {
332
340
int s ;
333
- for (;;) {
334
- if ((s = status ) < 0 )
335
- break ;
336
- if (casStatus (s , s | (DONE | ABNORMAL ))) {
337
- signalWaiters ();
338
- break ;
339
- }
340
- }
341
+ if ((s = status ) >= 0 &&
342
+ (s = getAndBitwiseOrStatus (DONE | ABNORMAL )) >= 0 )
343
+ signalWaiters ();
341
344
return s ;
342
345
}
343
346
@@ -481,7 +484,7 @@ else if (casAux(a, next))
481
484
*/
482
485
private int awaitDone (boolean interruptible , long deadline ) {
483
486
ForkJoinWorkerThread wt ; ForkJoinPool p ; ForkJoinPool .WorkQueue q ;
484
- Thread t ; boolean internal ; int s ;
487
+ Thread t ; boolean internal ; int s , ss ;
485
488
if (internal =
486
489
(t = Thread .currentThread ()) instanceof ForkJoinWorkerThread ) {
487
490
p = (wt = (ForkJoinWorkerThread )t ).pool ;
@@ -492,7 +495,7 @@ private int awaitDone(boolean interruptible, long deadline) {
492
495
return (((s = (p == null ) ? 0 :
493
496
((this instanceof CountedCompleter ) ?
494
497
p .helpComplete (this , q , internal ) :
495
- ( this instanceof InterruptibleTask ) && ! internal ? status :
498
+ ! internal && (( ss = status ) & NO_USER_HELP ) != 0 ? ss :
496
499
p .helpJoin (this , q , internal ))) < 0 )) ? s :
497
500
awaitDone (internal ? p : null , s , interruptible , deadline );
498
501
}
@@ -642,7 +645,7 @@ public final ForkJoinTask<V> fork() {
642
645
p = wt .pool ;
643
646
}
644
647
else
645
- q = (p = ForkJoinPool .common ).externalSubmissionQueue ();
648
+ q = (p = ForkJoinPool .common ).externalSubmissionQueue (false );
646
649
q .push (this , p , internal );
647
650
return this ;
648
651
}
@@ -1160,7 +1163,7 @@ public static void helpQuiesce() {
1160
1163
*/
1161
1164
public void reinitialize () {
1162
1165
aux = null ;
1163
- status = 0 ;
1166
+ status &= NO_USER_HELP ;
1164
1167
}
1165
1168
1166
1169
/**
@@ -1414,7 +1417,8 @@ public final boolean compareAndSetForkJoinTaskTag(short expect, short update) {
1414
1417
* @return the task
1415
1418
*/
1416
1419
public static ForkJoinTask <?> adapt (Runnable runnable ) {
1417
- return new AdaptedRunnableAction (runnable );
1420
+ return new AdaptedRunnableAction (
1421
+ Objects .requireNonNull (runnable ));
1418
1422
}
1419
1423
1420
1424
/**
@@ -1428,7 +1432,8 @@ public static ForkJoinTask<?> adapt(Runnable runnable) {
1428
1432
* @return the task
1429
1433
*/
1430
1434
public static <T > ForkJoinTask <T > adapt (Runnable runnable , T result ) {
1431
- return new AdaptedRunnable <T >(runnable , result );
1435
+ return new AdaptedRunnable <T >(
1436
+ Objects .requireNonNull (runnable ), result );
1432
1437
}
1433
1438
1434
1439
/**
@@ -1442,7 +1447,8 @@ public static <T> ForkJoinTask<T> adapt(Runnable runnable, T result) {
1442
1447
* @return the task
1443
1448
*/
1444
1449
public static <T > ForkJoinTask <T > adapt (Callable <? extends T > callable ) {
1445
- return new AdaptedCallable <T >(callable );
1450
+ return new AdaptedCallable <T >(
1451
+ Objects .requireNonNull (callable ));
1446
1452
}
1447
1453
1448
1454
/**
@@ -1460,7 +1466,8 @@ public static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable) {
1460
1466
* @since 19
1461
1467
*/
1462
1468
public static <T > ForkJoinTask <T > adaptInterruptible (Callable <? extends T > callable ) {
1463
- return new AdaptedInterruptibleCallable <T >(callable );
1469
+ return new AdaptedInterruptibleCallable <T >(
1470
+ Objects .requireNonNull (callable ));
1464
1471
}
1465
1472
1466
1473
/**
@@ -1479,7 +1486,8 @@ public static <T> ForkJoinTask<T> adaptInterruptible(Callable<? extends T> calla
1479
1486
* @since 22
1480
1487
*/
1481
1488
public static <T > ForkJoinTask <T > adaptInterruptible (Runnable runnable , T result ) {
1482
- return new AdaptedInterruptibleRunnable <T >(runnable , result );
1489
+ return new AdaptedInterruptibleRunnable <T >(
1490
+ Objects .requireNonNull (runnable ), result );
1483
1491
}
1484
1492
1485
1493
/**
@@ -1497,7 +1505,8 @@ public static <T> ForkJoinTask<T> adaptInterruptible(Runnable runnable, T result
1497
1505
* @since 22
1498
1506
*/
1499
1507
public static ForkJoinTask <?> adaptInterruptible (Runnable runnable ) {
1500
- return new AdaptedInterruptibleRunnable <Void >(runnable , null );
1508
+ return new AdaptedInterruptibleRunnable <Void >(
1509
+ Objects .requireNonNull (runnable ), null );
1501
1510
}
1502
1511
1503
1512
// Serialization support
@@ -1556,7 +1565,6 @@ static final class AdaptedRunnable<T> extends ForkJoinTask<T>
1556
1565
@ SuppressWarnings ("serial" ) // Conditionally serializable
1557
1566
T result ;
1558
1567
AdaptedRunnable (Runnable runnable , T result ) {
1559
- Objects .requireNonNull (runnable );
1560
1568
this .runnable = runnable ;
1561
1569
this .result = result ; // OK to set this even before completion
1562
1570
}
@@ -1578,7 +1586,6 @@ static final class AdaptedRunnableAction extends ForkJoinTask<Void>
1578
1586
@ SuppressWarnings ("serial" ) // Conditionally serializable
1579
1587
final Runnable runnable ;
1580
1588
AdaptedRunnableAction (Runnable runnable ) {
1581
- Objects .requireNonNull (runnable );
1582
1589
this .runnable = runnable ;
1583
1590
}
1584
1591
public final Void getRawResult () { return null ; }
@@ -1601,7 +1608,6 @@ static final class AdaptedCallable<T> extends ForkJoinTask<T>
1601
1608
@ SuppressWarnings ("serial" ) // Conditionally serializable
1602
1609
T result ;
1603
1610
AdaptedCallable (Callable <? extends T > callable ) {
1604
- Objects .requireNonNull (callable );
1605
1611
this .callable = callable ;
1606
1612
}
1607
1613
public final T getRawResult () { return result ; }
@@ -1636,6 +1642,9 @@ public String toString() {
1636
1642
abstract static class InterruptibleTask <T > extends ForkJoinTask <T >
1637
1643
implements RunnableFuture <T > {
1638
1644
transient volatile Thread runner ;
1645
+ InterruptibleTask () {
1646
+ setNoUserHelp ();
1647
+ }
1639
1648
abstract T compute () throws Exception ;
1640
1649
public final boolean exec () {
1641
1650
Thread .interrupted ();
@@ -1655,20 +1664,29 @@ public final boolean exec() {
1655
1664
} finally {
1656
1665
runner = null ;
1657
1666
}
1667
+ return postExec ();
1668
+ }
1669
+ boolean postExec () { // cleanup and return completion status to doExec
1658
1670
return true ;
1659
1671
}
1672
+ final boolean interruptIfRunning (boolean enabled ) {
1673
+ Thread t ;
1674
+ if ((t = runner ) == null ) // return false if not running
1675
+ return false ;
1676
+ if (enabled ) {
1677
+ try {
1678
+ t .interrupt ();
1679
+ } catch (Throwable ignore ) {
1680
+ }
1681
+ }
1682
+ return true ;
1683
+ }
1660
1684
public boolean cancel (boolean mayInterruptIfRunning ) {
1661
- Thread t ;
1662
- if (trySetCancelled () >= 0 ) {
1663
- if (mayInterruptIfRunning && (t = runner ) != null ) {
1664
- try {
1665
- t .interrupt ();
1666
- } catch (Throwable ignore ) {
1667
- }
1668
- }
1669
- return true ;
1670
- }
1671
- return isCancelled ();
1685
+ int s ;
1686
+ if ((s = trySetCancelled ()) < 0 )
1687
+ return ((s & (ABNORMAL | THROWN )) == ABNORMAL );
1688
+ interruptIfRunning (mayInterruptIfRunning );
1689
+ return true ;
1672
1690
}
1673
1691
public final void run () { quietlyInvoke (); }
1674
1692
Object adaptee () { return null ; } // for printing and diagnostics
@@ -1690,7 +1708,6 @@ static final class AdaptedInterruptibleCallable<T> extends InterruptibleTask<T>
1690
1708
@ SuppressWarnings ("serial" ) // Conditionally serializable
1691
1709
T result ;
1692
1710
AdaptedInterruptibleCallable (Callable <? extends T > callable ) {
1693
- Objects .requireNonNull (callable );
1694
1711
this .callable = callable ;
1695
1712
}
1696
1713
public final T getRawResult () { return result ; }
@@ -1709,7 +1726,6 @@ static final class AdaptedInterruptibleRunnable<T> extends InterruptibleTask<T>
1709
1726
@ SuppressWarnings ("serial" ) // Conditionally serializable
1710
1727
final T result ;
1711
1728
AdaptedInterruptibleRunnable (Runnable runnable , T result ) {
1712
- Objects .requireNonNull (runnable );
1713
1729
this .runnable = runnable ;
1714
1730
this .result = result ;
1715
1731
}
@@ -1727,7 +1743,6 @@ static final class RunnableExecuteAction extends InterruptibleTask<Void> {
1727
1743
@ SuppressWarnings ("serial" ) // Conditionally serializable
1728
1744
final Runnable runnable ;
1729
1745
RunnableExecuteAction (Runnable runnable ) {
1730
- Objects .requireNonNull (runnable );
1731
1746
this .runnable = runnable ;
1732
1747
}
1733
1748
public final Void getRawResult () { return null ; }
@@ -1793,9 +1808,11 @@ final T invokeAny(Collection<? extends Callable<T>> tasks,
1793
1808
throw new NullPointerException ();
1794
1809
InvokeAnyTask <T > t = null ; // list of submitted tasks
1795
1810
try {
1796
- for (Callable <T > c : tasks )
1811
+ for (Callable <T > c : tasks ) {
1812
+ Objects .requireNonNull (c );
1797
1813
pool .execute ((ForkJoinTask <?>)
1798
1814
(t = new InvokeAnyTask <T >(c , this , t )));
1815
+ }
1799
1816
return timed ? get (nanos , TimeUnit .NANOSECONDS ) : get ();
1800
1817
} finally {
1801
1818
for (; t != null ; t = t .pred )
@@ -1822,7 +1839,6 @@ static final class InvokeAnyTask<T> extends InterruptibleTask<Void> {
1822
1839
final InvokeAnyTask <T > pred ; // to traverse on cancellation
1823
1840
InvokeAnyTask (Callable <T > callable , InvokeAnyRoot <T > root ,
1824
1841
InvokeAnyTask <T > pred ) {
1825
- Objects .requireNonNull (callable );
1826
1842
this .callable = callable ;
1827
1843
this .root = root ;
1828
1844
this .pred = pred ;
@@ -1857,4 +1873,39 @@ final void onRootCompletion() {
1857
1873
public final void setRawResult (Void v ) { }
1858
1874
final Object adaptee () { return callable ; }
1859
1875
}
1876
+
1877
+ /**
1878
+ * Adapter for Callable-based interruptible tasks with timeout actions.
1879
+ */
1880
+ @ SuppressWarnings ("serial" ) // Conditionally serializable
1881
+ static final class CallableWithTimeout <T > extends InterruptibleTask <T > {
1882
+ Callable <? extends T > callable ; // nulled out after use
1883
+ ForkJoinTask <?> timeoutAction ;
1884
+ T result ;
1885
+ CallableWithTimeout (Callable <? extends T > callable ,
1886
+ ForkJoinTask <?> timeoutAction ) {
1887
+ this .callable = callable ;
1888
+ this .timeoutAction = timeoutAction ;
1889
+ }
1890
+ public final T getRawResult () { return result ; }
1891
+ public final void setRawResult (T v ) { result = v ; }
1892
+ final Object adaptee () { return callable ; }
1893
+ final T compute () throws Exception {
1894
+ Callable <? extends T > c ;
1895
+ return ((c = callable ) != null ) ? c .call () : null ;
1896
+ }
1897
+ final boolean postExec () { // cancel timeout action
1898
+ ForkJoinTask <?> t ;
1899
+ callable = null ;
1900
+ if ((t = timeoutAction ) != null ) {
1901
+ timeoutAction = null ;
1902
+ try {
1903
+ t .cancel (false );
1904
+ } catch (Error | RuntimeException ex ) {
1905
+ }
1906
+ }
1907
+ return true ;
1908
+ }
1909
+ }
1910
+
1860
1911
}
0 commit comments