1364 |
|
|
1365 |
|
/** A customized variant of Spliterators.IteratorSpliterator */ |
1366 |
|
static final class CLDSpliterator<E> implements Spliterator<E> { |
1367 |
< |
static final int MAX_BATCH = 1 << 20; // max batch array size; |
1368 |
< |
static final int MAX_QUEUED = 1 << 12; // max task backlog |
1367 |
> |
static final int MAX_BATCH = 1 << 25; // max batch array size; |
1368 |
|
final ConcurrentLinkedDeque<E> queue; |
1369 |
|
Node<E> current; // current node; null until initialized |
1370 |
|
int batch; // batch size for splits |
1374 |
|
} |
1375 |
|
|
1376 |
|
public Spliterator<E> trySplit() { |
1377 |
< |
Node<E> p; int b; |
1377 |
> |
Node<E> p; |
1378 |
|
final ConcurrentLinkedDeque<E> q = this.queue; |
1379 |
+ |
int b = batch; |
1380 |
+ |
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
1381 |
|
if (!exhausted && |
1382 |
|
((p = current) != null || (p = q.first()) != null)) { |
1383 |
|
if (p.item == null && p == (p = p.next)) |
1384 |
|
current = p = q.first(); |
1385 |
< |
if (p != null && p.next != null && |
1385 |
< |
((b = batch) < MAX_QUEUED || |
1386 |
< |
ForkJoinTask.getQueuedTaskCount() < MAX_QUEUED)) { |
1387 |
< |
int n = batch = (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
1385 |
> |
if (p != null && p.next != null) { |
1386 |
|
Object[] a; |
1387 |
|
try { |
1388 |
|
a = new Object[n]; |
1398 |
|
} while (p != null && i < n); |
1399 |
|
if ((current = p) == null) |
1400 |
|
exhausted = true; |
1401 |
< |
return Spliterators.spliterator |
1402 |
< |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
1403 |
< |
Spliterator.CONCURRENT); |
1401 |
> |
if (i > 0) { |
1402 |
> |
batch = i; |
1403 |
> |
return Spliterators.spliterator |
1404 |
> |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
1405 |
> |
Spliterator.CONCURRENT); |
1406 |
> |
} |
1407 |
|
} |
1408 |
|
} |
1409 |
|
return null; |