17 |
|
* subclassable solely for the sake of adding functionality -- there |
18 |
|
* are no overridable methods dealing with scheduling or |
19 |
|
* execution. However, you can override initialization and termination |
20 |
< |
* cleanup methods surrounding the main task processing loop. If you |
21 |
< |
* do create such a subclass, you will also need to supply a custom |
20 |
> |
* methods surrounding the main task processing loop. If you do |
21 |
> |
* create such a subclass, you will also need to supply a custom |
22 |
|
* ForkJoinWorkerThreadFactory to use it in a ForkJoinPool. |
23 |
|
* |
24 |
|
*/ |
199 |
|
long lastEventCount; |
200 |
|
|
201 |
|
/** |
202 |
+ |
* True if use local fifo, not default lifo, for local polling |
203 |
+ |
*/ |
204 |
+ |
private boolean locallyFifo; |
205 |
+ |
|
206 |
+ |
/** |
207 |
|
* Creates a ForkJoinWorkerThread operating in the given pool. |
208 |
|
* @param pool the pool this thread works in |
209 |
|
* @throws NullPointerException if pool is null |
237 |
|
return poolIndex; |
238 |
|
} |
239 |
|
|
240 |
+ |
/** |
241 |
+ |
* Establishes local first-in-first-out scheduling mode for forked |
242 |
+ |
* tasks that are never joined. |
243 |
+ |
* @param async if true, use locally FIFO scheduling |
244 |
+ |
*/ |
245 |
+ |
void setAsyncMode(boolean async) { |
246 |
+ |
locallyFifo = async; |
247 |
+ |
} |
248 |
|
|
249 |
|
// Runstate management |
250 |
|
|
447 |
|
* either empty or contended. |
448 |
|
* @return a task, or null if none or contended. |
449 |
|
*/ |
450 |
< |
private ForkJoinTask<?> deqTask() { |
450 |
> |
final ForkJoinTask<?> deqTask() { |
451 |
|
ForkJoinTask<?> t; |
452 |
|
ForkJoinTask<?>[] q; |
453 |
|
int i; |
501 |
|
} |
502 |
|
|
503 |
|
/** |
504 |
< |
* Returns next task to pop. |
504 |
> |
* Returns next task. |
505 |
|
*/ |
506 |
|
final ForkJoinTask<?> peekTask() { |
507 |
|
ForkJoinTask<?>[] q = queue; |
508 |
< |
return q == null? null : q[(sp - 1) & (q.length - 1)]; |
508 |
> |
if (q == null) |
509 |
> |
return null; |
510 |
> |
int mask = q.length - 1; |
511 |
> |
int i = locallyFifo? base : (sp - 1); |
512 |
> |
return q[i & mask]; |
513 |
|
} |
514 |
|
|
515 |
|
/** |
587 |
|
} |
588 |
|
|
589 |
|
/** |
590 |
< |
* Pops or steals a task |
590 |
> |
* gets and removes a local or stolen a task |
591 |
|
* @return a task, if available |
592 |
|
*/ |
593 |
|
final ForkJoinTask<?> pollTask() { |
594 |
< |
ForkJoinTask<?> t = popTask(); |
594 |
> |
ForkJoinTask<?> t = locallyFifo? deqTask() : popTask(); |
595 |
|
if (t == null && (t = scan()) != null) |
596 |
|
++stealCount; |
597 |
|
return t; |
598 |
|
} |
599 |
|
|
600 |
|
/** |
601 |
+ |
* gets a local task |
602 |
+ |
* @return a task, if available |
603 |
+ |
*/ |
604 |
+ |
final ForkJoinTask<?> pollLocalTask() { |
605 |
+ |
return locallyFifo? deqTask() : popTask(); |
606 |
+ |
} |
607 |
+ |
|
608 |
+ |
/** |
609 |
|
* Returns a pool submission, if one exists, activating first. |
610 |
|
* @return a submission, if available |
611 |
|
*/ |
632 |
|
} |
633 |
|
|
634 |
|
/** |
635 |
+ |
* Drains tasks to given collection c |
636 |
+ |
* @return the number of tasks drained |
637 |
+ |
*/ |
638 |
+ |
final int drainTasksTo(Collection<ForkJoinTask<?>> c) { |
639 |
+ |
int n = 0; |
640 |
+ |
ForkJoinTask<?> t; |
641 |
+ |
while (base != sp && (t = deqTask()) != null) { |
642 |
+ |
c.add(t); |
643 |
+ |
++n; |
644 |
+ |
} |
645 |
+ |
return n; |
646 |
+ |
} |
647 |
+ |
|
648 |
+ |
/** |
649 |
|
* Get and clear steal count for accumulation by pool. Called |
650 |
|
* only when known to be idle (in pool.sync and termination). |
651 |
|
*/ |