833 |
|
} |
834 |
|
} |
835 |
|
|
836 |
+ |
/** A customized variant of Spliterators.IteratorSpliterator */ |
837 |
|
static final class LBQSpliterator<E> implements Spliterator<E> { |
838 |
< |
// Similar idea to ConcurrentLinkedQueue spliterator |
839 |
< |
static final int MAX_BATCH = 1 << 11; // saturate batch size |
838 |
> |
static final int MAX_BATCH = 1 << 20; // max batch array size; |
839 |
> |
static final int MAX_QUEUED = 1 << 12; // max task backlog |
840 |
|
final LinkedBlockingQueue<E> queue; |
841 |
|
Node<E> current; // current node; null until initialized |
842 |
|
int batch; // batch size for splits |
850 |
|
public long estimateSize() { return est; } |
851 |
|
|
852 |
|
public Spliterator<E> trySplit() { |
853 |
< |
int n; |
853 |
> |
int b; |
854 |
|
final LinkedBlockingQueue<E> q = this.queue; |
855 |
< |
if (!exhausted && (n = batch + 1) > 0 && n <= MAX_BATCH) { |
856 |
< |
Object[] a = new Object[batch = n]; |
855 |
> |
if (!exhausted && |
856 |
> |
((b = batch) < MAX_QUEUED || |
857 |
> |
java.util.concurrent.ForkJoinTask.getQueuedTaskCount() < MAX_QUEUED)) { |
858 |
> |
int n = batch = (b >= MAX_BATCH)? MAX_BATCH : b + 1; |
859 |
> |
Object[] a; |
860 |
> |
try { |
861 |
> |
a = new Object[n]; |
862 |
> |
} catch (OutOfMemoryError oome) { |
863 |
> |
return null; |
864 |
> |
} |
865 |
|
int i = 0; |
866 |
|
Node<E> p = current; |
867 |
|
q.fullyLock(); |
879 |
|
est = 0L; |
880 |
|
exhausted = true; |
881 |
|
} |
882 |
< |
else if ((est -= i) <= 0L) |
883 |
< |
est = 1L; |
882 |
> |
else if ((est -= i) < 0L) |
883 |
> |
est = 0L; |
884 |
|
return Spliterators.spliterator |
885 |
|
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
886 |
|
Spliterator.CONCURRENT); |