1130 |
|
|
1131 |
|
/** A customized variant of Spliterators.IteratorSpliterator */ |
1132 |
|
static final class LBDSpliterator<E> implements Spliterator<E> { |
1133 |
< |
static final int MAX_BATCH = 1 << 20; // max batch array size; |
1134 |
< |
static final int MAX_QUEUED = 1 << 12; // max task backlog |
1133 |
> |
static final int MAX_BATCH = 1 << 25; // max batch array size; |
1134 |
|
final LinkedBlockingDeque<E> queue; |
1135 |
|
Node<E> current; // current node; null until initialized |
1136 |
|
int batch; // batch size for splits |
1144 |
|
public long estimateSize() { return est; } |
1145 |
|
|
1146 |
|
public Spliterator<E> trySplit() { |
1147 |
< |
int b; |
1147 |
> |
Node<E> h; |
1148 |
|
final LinkedBlockingDeque<E> q = this.queue; |
1149 |
< |
final ReentrantLock lock = q.lock; |
1149 |
> |
int b = batch; |
1150 |
> |
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
1151 |
|
if (!exhausted && |
1152 |
< |
((b = batch) < MAX_QUEUED || |
1153 |
< |
ForkJoinTask.getQueuedTaskCount() < MAX_QUEUED)) { |
1154 |
< |
int n = batch = (b >= MAX_BATCH) ? MAX_BATCH : b + 1; |
1152 |
> |
((h = current) != null || (h = q.first) != null) && |
1153 |
> |
h.next != null) { |
1154 |
|
Object[] a; |
1155 |
|
try { |
1156 |
|
a = new Object[n]; |
1157 |
|
} catch (OutOfMemoryError oome) { |
1158 |
|
return null; |
1159 |
|
} |
1160 |
+ |
final ReentrantLock lock = q.lock; |
1161 |
|
int i = 0; |
1162 |
|
Node<E> p = current; |
1163 |
|
lock.lock(); |
1177 |
|
} |
1178 |
|
else if ((est -= i) < 0L) |
1179 |
|
est = 0L; |
1180 |
< |
return Spliterators.spliterator |
1181 |
< |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
1182 |
< |
Spliterator.CONCURRENT); |
1180 |
> |
if (i > 0) { |
1181 |
> |
batch = i; |
1182 |
> |
return Spliterators.spliterator |
1183 |
> |
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL | |
1184 |
> |
Spliterator.CONCURRENT); |
1185 |
> |
} |
1186 |
|
} |
1187 |
|
return null; |
1188 |
|
} |