1362 |
|
Node<E> nextNode(Node<E> p) { return pred(p); } |
1363 |
|
} |
1364 |
|
|
1365 |
< |
// Same idea as ConcurrentLinkedQueue Spliterator |
1365 |
> |
/** A customized variant of Spliterators.IteratorSpliterator */ |
1366 |
|
static final class CLDSpliterator<E> implements Spliterator<E> { |
1367 |
< |
static final int MAX_BATCH = 1 << 10; // saturate batch size |
1367 |
> |
static final int MAX_BATCH = 1 << 20; // max batch array size; |
1368 |
> |
static final int MAX_QUEUED = 1 << 12; // max task backlog |
1369 |
|
final ConcurrentLinkedDeque<E> queue; |
1370 |
|
Node<E> current; // current node; null until initialized |
1371 |
|
int batch; // batch size for splits |
1375 |
|
} |
1376 |
|
|
1377 |
|
public Spliterator<E> trySplit() { |
1378 |
< |
Node<E> p; int n; |
1378 |
> |
Node<E> p; int b; |
1379 |
|
final ConcurrentLinkedDeque<E> q = this.queue; |
1380 |
< |
if (!exhausted && (n = batch + 1) > 0 && n <= MAX_BATCH && |
1380 |
> |
if (!exhausted && |
1381 |
|
((p = current) != null || (p = q.first()) != null)) { |
1382 |
|
if (p.item == null && p == (p = p.next)) |
1383 |
|
current = p = q.first(); |
1384 |
< |
if (p != null && p.next != null) { |
1385 |
< |
Object[] a = new Object[batch = n]; |
1384 |
> |
if (p != null && p.next != null && |
1385 |
> |
((b = batch) < MAX_QUEUED || |
1386 |
> |
java.util.concurrent.ForkJoinTask.getQueuedTaskCount() < MAX_QUEUED)) { |
1387 |
> |
int n = batch = (b >= MAX_BATCH)? MAX_BATCH : b + 1; |
1388 |
> |
Object[] a; |
1389 |
> |
try { |
1390 |
> |
a = new Object[n]; |
1391 |
> |
} catch (OutOfMemoryError oome) { |
1392 |
> |
return null; |
1393 |
> |
} |
1394 |
|
int i = 0; |
1395 |
|
do { |
1396 |
|
if ((a[i] = p.item) != null) |