835 |
|
|
836 |
|
/** A customized variant of Spliterators.IteratorSpliterator */ |
837 |
|
static final class LBQSpliterator<E> implements Spliterator<E> { |
838 |
< |
static final int MAX_BATCH = 1 << 20; // max batch array size; |
839 |
< |
static final int MAX_QUEUED = 1 << 12; // max task backlog |
838 |
> |
static final int MAX_BATCH = 1 << 25; // max batch array size; |
839 |
|
final LinkedBlockingQueue<E> queue; |
840 |
|
Node<E> current; // current node; null until initialized |
841 |
|
int batch; // batch size for splits |
849 |
|
public long estimateSize() { return est; } |
850 |
|
|
851 |
|
public Spliterator<E> trySplit() { |
852 |
< |
int b; |
852 |
> |
Node<E> h; |
853 |
|
final LinkedBlockingQueue<E> q = this.queue; |
854 |
+ |
int b = batch; |
855 |
+ |
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
856 |
|
if (!exhausted && |
857 |
< |
((b = batch) < MAX_QUEUED || |
858 |
< |
ForkJoinTask.getQueuedTaskCount() < MAX_QUEUED)) { |
858 |
< |
int n = batch = (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
857 |
> |
((h = current) != null || (h = q.head.next) != null) && |
858 |
> |
h.next != null) { |
859 |
|
Object[] a; |
860 |
|
try { |
861 |
|
a = new Object[n]; |
881 |
|
} |
882 |
|
else if ((est -= i) < 0L) |
883 |
|
est = 0L; |
884 |
< |
return Spliterators.spliterator |
885 |
< |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
886 |
< |
Spliterator.CONCURRENT); |
884 |
> |
if (i > 0) { |
885 |
> |
batch = i; |
886 |
> |
return Spliterators.spliterator |
887 |
> |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
888 |
> |
Spliterator.CONCURRENT); |
889 |
> |
} |
890 |
|
} |
891 |
|
return null; |
892 |
|
} |