5 |
|
*/ |
6 |
|
|
7 |
|
package jsr166e; |
8 |
– |
|
8 |
|
/** |
9 |
|
* A {@link ForkJoinTask} with a completion action |
10 |
|
* performed when triggered and there are no remaining pending |
141 |
|
* |
142 |
|
* As a further improvement, notice that the left task need not even |
143 |
|
* exist. Instead of creating a new one, we can iterate using the |
144 |
< |
* original task, and add a pending count for each fork: |
144 |
> |
* original task, and add a pending count for each fork. Additionally, |
145 |
> |
* this version uses {@code helpComplete} to streamline assistance in |
146 |
> |
* the execution of forked tasks. |
147 |
|
* |
148 |
|
* <pre> {@code |
149 |
|
* class ForEach<E> ... |
157 |
|
* } |
158 |
|
* if (h > l) |
159 |
|
* op.apply(array[l]); |
160 |
< |
* tryComplete(); |
160 |
> |
* helpComplete(); |
161 |
|
* } |
162 |
|
* }</pre> |
163 |
|
* |
379 |
|
} |
380 |
|
|
381 |
|
/** |
382 |
+ |
* Returns the root of the current computation; i.e., this |
383 |
+ |
* task if it has no completer, else its completer's root. |
384 |
+ |
* |
385 |
+ |
* @return the root of the current computation |
386 |
+ |
*/ |
387 |
+ |
public final CountedCompleter<?> getRoot() { |
388 |
+ |
CountedCompleter<?> a = this, p; |
389 |
+ |
while ((p = a.completer) != null) |
390 |
+ |
a = p; |
391 |
+ |
return a; |
392 |
+ |
} |
393 |
+ |
|
394 |
+ |
/** |
395 |
|
* If the pending count is nonzero, decrements the count; |
396 |
|
* otherwise invokes {@link #onCompletion} and then similarly |
397 |
|
* tries to complete this task's completer, if one exists, |
413 |
|
} |
414 |
|
|
415 |
|
/** |
416 |
+ |
* Identical to {@link #tryComplete}, but may additionally execute |
417 |
+ |
* other tasks within the current computation (i.e., those |
418 |
+ |
* with the same {@link #getRoot}. |
419 |
+ |
*/ |
420 |
+ |
public final void helpComplete() { |
421 |
+ |
CountedCompleter<?> a = this, s = a; |
422 |
+ |
for (int c;;) { |
423 |
+ |
if ((c = a.pending) == 0) { |
424 |
+ |
a.onCompletion(s); |
425 |
+ |
if ((a = (s = a).completer) == null) { |
426 |
+ |
s.quietlyComplete(); |
427 |
+ |
return; |
428 |
+ |
} |
429 |
+ |
} |
430 |
+ |
else if (U.compareAndSwapInt(a, PENDING, c, c - 1)) { |
431 |
+ |
CountedCompleter<?> root = a.getRoot(); |
432 |
+ |
Thread thread = Thread.currentThread(); |
433 |
+ |
ForkJoinPool.WorkQueue wq = |
434 |
+ |
(thread instanceof ForkJoinWorkerThread)? |
435 |
+ |
((ForkJoinWorkerThread)thread).workQueue : null; |
436 |
+ |
ForkJoinTask<?> t; |
437 |
+ |
while ((t = (wq != null) ? wq.popCC(root) : |
438 |
+ |
ForkJoinPool.popCCFromCommonPool(root)) != null) { |
439 |
+ |
t.doExec(); |
440 |
+ |
if (root.isDone()) |
441 |
+ |
break; |
442 |
+ |
} |
443 |
+ |
return; |
444 |
+ |
} |
445 |
+ |
} |
446 |
+ |
} |
447 |
+ |
|
448 |
+ |
/** |
449 |
|
* Regardless of pending count, invokes {@link #onCompletion}, |
450 |
|
* marks this task as complete and further triggers {@link |
451 |
|
* #tryComplete} on this task's completer, if one exists. This |
512 |
|
} |
513 |
|
} |
514 |
|
|
468 |
– |
|
515 |
|
/** |
516 |
|
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. |
517 |
|
* Replace with a simple call to Unsafe.getUnsafe when integrating |