772 |
|
|
773 |
|
/** A customized variant of Spliterators.IteratorSpliterator */ |
774 |
|
static final class CLQSpliterator<E> implements Spliterator<E> { |
775 |
< |
static final int MAX_BATCH = 1 << 20; // max batch array size; |
776 |
< |
static final int MAX_QUEUED = 1 << 12; // max task backlog |
775 |
> |
static final int MAX_BATCH = 1 << 25; // max batch array size; |
776 |
|
final ConcurrentLinkedQueue<E> queue; |
777 |
|
Node<E> current; // current node; null until initialized |
778 |
|
int batch; // batch size for splits |
782 |
|
} |
783 |
|
|
784 |
|
public Spliterator<E> trySplit() { |
785 |
< |
Node<E> p; int b; |
785 |
> |
Node<E> p; |
786 |
|
final ConcurrentLinkedQueue<E> q = this.queue; |
787 |
+ |
int b = batch; |
788 |
+ |
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
789 |
|
if (!exhausted && |
789 |
– |
((b = batch) < MAX_QUEUED || |
790 |
– |
ForkJoinTask.getQueuedTaskCount() < MAX_QUEUED) && |
790 |
|
((p = current) != null || (p = q.first()) != null) && |
791 |
|
p.next != null) { |
793 |
– |
int n = batch = (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
792 |
|
Object[] a; |
793 |
|
try { |
794 |
|
a = new Object[n]; |
804 |
|
} while (p != null && i < n); |
805 |
|
if ((current = p) == null) |
806 |
|
exhausted = true; |
807 |
< |
return Spliterators.spliterator |
808 |
< |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
809 |
< |
Spliterator.CONCURRENT); |
807 |
> |
if (i > 0) { |
808 |
> |
batch = i; |
809 |
> |
return Spliterators.spliterator |
810 |
> |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
811 |
> |
Spliterator.CONCURRENT); |
812 |
> |
} |
813 |
|
} |
814 |
|
return null; |
815 |
|
} |