906 |
|
} |
907 |
|
} |
908 |
|
|
909 |
< |
// Very similar to ConcurrentLinkedQueue spliterator |
909 |
> |
/** A customized variant of Spliterators.IteratorSpliterator */ |
910 |
|
static final class LTQSpliterator<E> implements Spliterator<E> { |
911 |
< |
static final int MAX_BATCH = 1 << 10; // saturate batch size |
911 |
> |
static final int MAX_BATCH = 1 << 20; // max batch array size; |
912 |
> |
static final int MAX_QUEUED = 1 << 12; // max task backlog |
913 |
|
final LinkedTransferQueue<E> queue; |
914 |
|
Node current; // current node; null until initialized |
915 |
|
int batch; // batch size for splits |
927 |
|
* not, we limit slowdowns by eventually returning null split. |
928 |
|
*/ |
929 |
|
public Spliterator<E> trySplit() { |
930 |
< |
Node p; int n; |
930 |
> |
Node p; int b; |
931 |
|
final LinkedTransferQueue<E> q = this.queue; |
932 |
< |
if (!exhausted && (n = batch + 1) > 0 && n <= MAX_BATCH && |
932 |
> |
if (!exhausted && |
933 |
> |
((b = batch) < MAX_QUEUED || |
934 |
> |
java.util.concurrent.ForkJoinTask.getQueuedTaskCount() < MAX_QUEUED) && |
935 |
|
((p = current) != null || (p = q.firstDataNode()) != null) && |
936 |
|
p.next != null) { |
937 |
< |
Object[] a = new Object[batch = n]; |
937 |
> |
int n = batch = (b >= MAX_BATCH)? MAX_BATCH : b + 1; |
938 |
> |
Object[] a; |
939 |
> |
try { |
940 |
> |
a = new Object[n]; |
941 |
> |
} catch (OutOfMemoryError oome) { |
942 |
> |
return null; |
943 |
> |
} |
944 |
|
int i = 0; |
945 |
|
do { |
946 |
|
if ((a[i] = p.item) != null) |