author | psandoz |
Thu, 16 Jan 2014 18:20:31 +0100 | |
changeset 22289 | bb9c71b84919 |
parent 19593 | ce0cd954351c |
child 25526 | d3cbdae6e9f9 |
permissions | -rw-r--r-- |
17182 | 1 |
/* |
2 |
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
package java.util.stream; |
|
26 |
||
27 |
import java.util.Spliterator; |
|
28 |
import java.util.concurrent.CountedCompleter; |
|
29 |
import java.util.function.IntFunction; |
|
30 |
||
31 |
/** |
|
32 |
* Factory for instances of a short-circuiting stateful intermediate operations |
|
33 |
* that produce subsequences of their input stream. |
|
34 |
* |
|
35 |
* @since 1.8 |
|
36 |
*/ |
|
37 |
final class SliceOps { |
|
38 |
||
39 |
// No instances |
|
40 |
private SliceOps() { } |
|
41 |
||
42 |
/** |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
43 |
* Calculates the sliced size given the current size, number of elements |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
44 |
* skip, and the number of elements to limit. |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
45 |
* |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
46 |
* @param size the current size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
47 |
* @param skip the number of elements to skip, assumed to be >= 0 |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
48 |
* @param limit the number of elements to limit, assumed to be >= 0, with |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
49 |
* a value of {@code Long.MAX_VALUE} if there is no limit |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
50 |
* @return the sliced size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
51 |
*/ |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
52 |
private static long calcSize(long size, long skip, long limit) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
53 |
return size >= 0 ? Math.max(-1, Math.min(size - skip, limit)) : -1; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
54 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
55 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
56 |
/** |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
57 |
* Calculates the slice fence, which is one past the index of the slice |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
58 |
* range |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
59 |
* @param skip the number of elements to skip, assumed to be >= 0 |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
60 |
* @param limit the number of elements to limit, assumed to be >= 0, with |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
61 |
* a value of {@code Long.MAX_VALUE} if there is no limit |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
62 |
* @return the slice fence. |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
63 |
*/ |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
64 |
private static long calcSliceFence(long skip, long limit) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
65 |
long sliceFence = limit >= 0 ? skip + limit : Long.MAX_VALUE; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
66 |
// Check for overflow |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
67 |
return (sliceFence >= 0) ? sliceFence : Long.MAX_VALUE; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
68 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
69 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
70 |
/** |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
71 |
* Creates a slice spliterator given a stream shape governing the |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
72 |
* spliterator type. Requires that the underlying Spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
73 |
* be SUBSIZED. |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
74 |
*/ |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
75 |
@SuppressWarnings("unchecked") |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
76 |
private static <P_IN> Spliterator<P_IN> sliceSpliterator(StreamShape shape, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
77 |
Spliterator<P_IN> s, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
78 |
long skip, long limit) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
79 |
assert s.hasCharacteristics(Spliterator.SUBSIZED); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
80 |
long sliceFence = calcSliceFence(skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
81 |
switch (shape) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
82 |
case REFERENCE: |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
83 |
return new StreamSpliterators |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
84 |
.SliceSpliterator.OfRef<>(s, skip, sliceFence); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
85 |
case INT_VALUE: |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
86 |
return (Spliterator<P_IN>) new StreamSpliterators |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
87 |
.SliceSpliterator.OfInt((Spliterator.OfInt) s, skip, sliceFence); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
88 |
case LONG_VALUE: |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
89 |
return (Spliterator<P_IN>) new StreamSpliterators |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
90 |
.SliceSpliterator.OfLong((Spliterator.OfLong) s, skip, sliceFence); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
91 |
case DOUBLE_VALUE: |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
92 |
return (Spliterator<P_IN>) new StreamSpliterators |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
93 |
.SliceSpliterator.OfDouble((Spliterator.OfDouble) s, skip, sliceFence); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
94 |
default: |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
95 |
throw new IllegalStateException("Unknown shape " + shape); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
96 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
97 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
98 |
|
19593 | 99 |
@SuppressWarnings("unchecked") |
100 |
private static <T> IntFunction<T[]> castingArray() { |
|
101 |
return size -> (T[]) new Object[size]; |
|
102 |
} |
|
103 |
||
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
104 |
/** |
17182 | 105 |
* Appends a "slice" operation to the provided stream. The slice operation |
106 |
* may be may be skip-only, limit-only, or skip-and-limit. |
|
107 |
* |
|
108 |
* @param <T> the type of both input and output elements |
|
109 |
* @param upstream a reference stream with element type T |
|
110 |
* @param skip the number of elements to skip. Must be >= 0. |
|
111 |
* @param limit the maximum size of the resulting stream, or -1 if no limit |
|
112 |
* is to be imposed |
|
113 |
*/ |
|
114 |
public static <T> Stream<T> makeRef(AbstractPipeline<?, T, ?> upstream, |
|
19593 | 115 |
long skip, long limit) { |
17182 | 116 |
if (skip < 0) |
117 |
throw new IllegalArgumentException("Skip must be non-negative: " + skip); |
|
118 |
||
19593 | 119 |
return new ReferencePipeline.StatefulOp<T, T>(upstream, StreamShape.REFERENCE, |
120 |
flags(limit)) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
121 |
Spliterator<T> unorderedSkipLimitSpliterator(Spliterator<T> s, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
122 |
long skip, long limit, long sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
123 |
if (skip <= sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
124 |
// Use just the limit if the number of elements |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
125 |
// to skip is <= the known pipeline size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
126 |
limit = limit >= 0 ? Math.min(limit, sizeIfKnown - skip) : sizeIfKnown - skip; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
127 |
skip = 0; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
128 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
129 |
return new StreamSpliterators.UnorderedSliceSpliterator.OfRef<>(s, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
130 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
131 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
132 |
@Override |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
133 |
<P_IN> Spliterator<T> opEvaluateParallelLazy(PipelineHelper<T> helper, Spliterator<P_IN> spliterator) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
134 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
135 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
136 |
return new StreamSpliterators.SliceSpliterator.OfRef<>( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
137 |
helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
138 |
skip, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
139 |
calcSliceFence(skip, limit)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
140 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
141 |
return unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
142 |
helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
143 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
144 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
145 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
146 |
// @@@ OOMEs will occur for LongStream.longs().filter(i -> true).limit(n) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
147 |
// regardless of the value of n |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
148 |
// Need to adjust the target size of splitting for the |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
149 |
// SliceTask from say (size / k) to say min(size / k, 1 << 14) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
150 |
// This will limit the size of the buffers created at the leaf nodes |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
151 |
// cancellation will be more aggressive cancelling later tasks |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
152 |
// if the target slice size has been reached from a given task, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
153 |
// cancellation should also clear local results if any |
19593 | 154 |
return new SliceTask<>(this, helper, spliterator, castingArray(), skip, limit). |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
155 |
invoke().spliterator(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
156 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
157 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
158 |
|
17182 | 159 |
@Override |
160 |
<P_IN> Node<T> opEvaluateParallel(PipelineHelper<T> helper, |
|
161 |
Spliterator<P_IN> spliterator, |
|
162 |
IntFunction<T[]> generator) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
163 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
164 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
165 |
// Because the pipeline is SIZED the slice spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
166 |
// can be created from the source, this requires matching |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
167 |
// to shape of the source, and is potentially more efficient |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
168 |
// than creating the slice spliterator from the pipeline |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
169 |
// wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
170 |
Spliterator<P_IN> s = sliceSpliterator(helper.getSourceShape(), spliterator, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
171 |
return Nodes.collect(helper, s, true, generator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
172 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
173 |
Spliterator<T> s = unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
174 |
helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
175 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
176 |
// Collect using this pipeline, which is empty and therefore |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
177 |
// can be used with the pipeline wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
178 |
// Note that we cannot create a slice spliterator from |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
179 |
// the source spliterator if the pipeline is not SIZED |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
180 |
return Nodes.collect(this, s, true, generator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
181 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
182 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
183 |
return new SliceTask<>(this, helper, spliterator, generator, skip, limit). |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
184 |
invoke(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
185 |
} |
17182 | 186 |
} |
187 |
||
188 |
@Override |
|
189 |
Sink<T> opWrapSink(int flags, Sink<T> sink) { |
|
19593 | 190 |
return new Sink.ChainedReference<T, T>(sink) { |
17182 | 191 |
long n = skip; |
192 |
long m = limit >= 0 ? limit : Long.MAX_VALUE; |
|
193 |
||
194 |
@Override |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
195 |
public void begin(long size) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
196 |
downstream.begin(calcSize(size, skip, m)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
197 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
198 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
199 |
@Override |
17182 | 200 |
public void accept(T t) { |
201 |
if (n == 0) { |
|
202 |
if (m > 0) { |
|
203 |
m--; |
|
204 |
downstream.accept(t); |
|
205 |
} |
|
206 |
} |
|
207 |
else { |
|
208 |
n--; |
|
209 |
} |
|
210 |
} |
|
211 |
||
212 |
@Override |
|
213 |
public boolean cancellationRequested() { |
|
214 |
return m == 0 || downstream.cancellationRequested(); |
|
215 |
} |
|
216 |
}; |
|
217 |
} |
|
218 |
}; |
|
219 |
} |
|
220 |
||
221 |
/** |
|
222 |
* Appends a "slice" operation to the provided IntStream. The slice |
|
223 |
* operation may be may be skip-only, limit-only, or skip-and-limit. |
|
224 |
* |
|
225 |
* @param upstream An IntStream |
|
226 |
* @param skip The number of elements to skip. Must be >= 0. |
|
227 |
* @param limit The maximum size of the resulting stream, or -1 if no limit |
|
228 |
* is to be imposed |
|
229 |
*/ |
|
230 |
public static IntStream makeInt(AbstractPipeline<?, Integer, ?> upstream, |
|
231 |
long skip, long limit) { |
|
232 |
if (skip < 0) |
|
233 |
throw new IllegalArgumentException("Skip must be non-negative: " + skip); |
|
234 |
||
235 |
return new IntPipeline.StatefulOp<Integer>(upstream, StreamShape.INT_VALUE, |
|
236 |
flags(limit)) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
237 |
Spliterator.OfInt unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
238 |
Spliterator.OfInt s, long skip, long limit, long sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
239 |
if (skip <= sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
240 |
// Use just the limit if the number of elements |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
241 |
// to skip is <= the known pipeline size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
242 |
limit = limit >= 0 ? Math.min(limit, sizeIfKnown - skip) : sizeIfKnown - skip; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
243 |
skip = 0; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
244 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
245 |
return new StreamSpliterators.UnorderedSliceSpliterator.OfInt(s, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
246 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
247 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
248 |
@Override |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
249 |
<P_IN> Spliterator<Integer> opEvaluateParallelLazy(PipelineHelper<Integer> helper, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
250 |
Spliterator<P_IN> spliterator) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
251 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
252 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
253 |
return new StreamSpliterators.SliceSpliterator.OfInt( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
254 |
(Spliterator.OfInt) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
255 |
skip, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
256 |
calcSliceFence(skip, limit)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
257 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
258 |
return unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
259 |
(Spliterator.OfInt) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
260 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
261 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
262 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
263 |
return new SliceTask<>(this, helper, spliterator, Integer[]::new, skip, limit). |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
264 |
invoke().spliterator(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
265 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
266 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
267 |
|
17182 | 268 |
@Override |
269 |
<P_IN> Node<Integer> opEvaluateParallel(PipelineHelper<Integer> helper, |
|
270 |
Spliterator<P_IN> spliterator, |
|
271 |
IntFunction<Integer[]> generator) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
272 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
273 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
274 |
// Because the pipeline is SIZED the slice spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
275 |
// can be created from the source, this requires matching |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
276 |
// to shape of the source, and is potentially more efficient |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
277 |
// than creating the slice spliterator from the pipeline |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
278 |
// wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
279 |
Spliterator<P_IN> s = sliceSpliterator(helper.getSourceShape(), spliterator, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
280 |
return Nodes.collectInt(helper, s, true); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
281 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
282 |
Spliterator.OfInt s = unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
283 |
(Spliterator.OfInt) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
284 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
285 |
// Collect using this pipeline, which is empty and therefore |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
286 |
// can be used with the pipeline wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
287 |
// Note that we cannot create a slice spliterator from |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
288 |
// the source spliterator if the pipeline is not SIZED |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
289 |
return Nodes.collectInt(this, s, true); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
290 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
291 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
292 |
return new SliceTask<>(this, helper, spliterator, generator, skip, limit). |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
293 |
invoke(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
294 |
} |
17182 | 295 |
} |
296 |
||
297 |
@Override |
|
298 |
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) { |
|
19593 | 299 |
return new Sink.ChainedInt<Integer>(sink) { |
17182 | 300 |
long n = skip; |
301 |
long m = limit >= 0 ? limit : Long.MAX_VALUE; |
|
302 |
||
303 |
@Override |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
304 |
public void begin(long size) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
305 |
downstream.begin(calcSize(size, skip, m)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
306 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
307 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
308 |
@Override |
17182 | 309 |
public void accept(int t) { |
310 |
if (n == 0) { |
|
311 |
if (m > 0) { |
|
312 |
m--; |
|
313 |
downstream.accept(t); |
|
314 |
} |
|
315 |
} |
|
316 |
else { |
|
317 |
n--; |
|
318 |
} |
|
319 |
} |
|
320 |
||
321 |
@Override |
|
322 |
public boolean cancellationRequested() { |
|
323 |
return m == 0 || downstream.cancellationRequested(); |
|
324 |
} |
|
325 |
}; |
|
326 |
} |
|
327 |
}; |
|
328 |
} |
|
329 |
||
330 |
/** |
|
331 |
* Appends a "slice" operation to the provided LongStream. The slice |
|
332 |
* operation may be may be skip-only, limit-only, or skip-and-limit. |
|
333 |
* |
|
334 |
* @param upstream A LongStream |
|
335 |
* @param skip The number of elements to skip. Must be >= 0. |
|
336 |
* @param limit The maximum size of the resulting stream, or -1 if no limit |
|
337 |
* is to be imposed |
|
338 |
*/ |
|
339 |
public static LongStream makeLong(AbstractPipeline<?, Long, ?> upstream, |
|
340 |
long skip, long limit) { |
|
341 |
if (skip < 0) |
|
342 |
throw new IllegalArgumentException("Skip must be non-negative: " + skip); |
|
343 |
||
344 |
return new LongPipeline.StatefulOp<Long>(upstream, StreamShape.LONG_VALUE, |
|
345 |
flags(limit)) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
346 |
Spliterator.OfLong unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
347 |
Spliterator.OfLong s, long skip, long limit, long sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
348 |
if (skip <= sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
349 |
// Use just the limit if the number of elements |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
350 |
// to skip is <= the known pipeline size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
351 |
limit = limit >= 0 ? Math.min(limit, sizeIfKnown - skip) : sizeIfKnown - skip; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
352 |
skip = 0; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
353 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
354 |
return new StreamSpliterators.UnorderedSliceSpliterator.OfLong(s, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
355 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
356 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
357 |
@Override |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
358 |
<P_IN> Spliterator<Long> opEvaluateParallelLazy(PipelineHelper<Long> helper, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
359 |
Spliterator<P_IN> spliterator) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
360 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
361 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
362 |
return new StreamSpliterators.SliceSpliterator.OfLong( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
363 |
(Spliterator.OfLong) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
364 |
skip, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
365 |
calcSliceFence(skip, limit)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
366 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
367 |
return unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
368 |
(Spliterator.OfLong) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
369 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
370 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
371 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
372 |
return new SliceTask<>(this, helper, spliterator, Long[]::new, skip, limit). |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
373 |
invoke().spliterator(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
374 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
375 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
376 |
|
17182 | 377 |
@Override |
378 |
<P_IN> Node<Long> opEvaluateParallel(PipelineHelper<Long> helper, |
|
379 |
Spliterator<P_IN> spliterator, |
|
380 |
IntFunction<Long[]> generator) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
381 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
382 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
383 |
// Because the pipeline is SIZED the slice spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
384 |
// can be created from the source, this requires matching |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
385 |
// to shape of the source, and is potentially more efficient |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
386 |
// than creating the slice spliterator from the pipeline |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
387 |
// wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
388 |
Spliterator<P_IN> s = sliceSpliterator(helper.getSourceShape(), spliterator, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
389 |
return Nodes.collectLong(helper, s, true); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
390 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
391 |
Spliterator.OfLong s = unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
392 |
(Spliterator.OfLong) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
393 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
394 |
// Collect using this pipeline, which is empty and therefore |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
395 |
// can be used with the pipeline wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
396 |
// Note that we cannot create a slice spliterator from |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
397 |
// the source spliterator if the pipeline is not SIZED |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
398 |
return Nodes.collectLong(this, s, true); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
399 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
400 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
401 |
return new SliceTask<>(this, helper, spliterator, generator, skip, limit). |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
402 |
invoke(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
403 |
} |
17182 | 404 |
} |
405 |
||
406 |
@Override |
|
407 |
Sink<Long> opWrapSink(int flags, Sink<Long> sink) { |
|
19593 | 408 |
return new Sink.ChainedLong<Long>(sink) { |
17182 | 409 |
long n = skip; |
410 |
long m = limit >= 0 ? limit : Long.MAX_VALUE; |
|
411 |
||
412 |
@Override |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
413 |
public void begin(long size) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
414 |
downstream.begin(calcSize(size, skip, m)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
415 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
416 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
417 |
@Override |
17182 | 418 |
public void accept(long t) { |
419 |
if (n == 0) { |
|
420 |
if (m > 0) { |
|
421 |
m--; |
|
422 |
downstream.accept(t); |
|
423 |
} |
|
424 |
} |
|
425 |
else { |
|
426 |
n--; |
|
427 |
} |
|
428 |
} |
|
429 |
||
430 |
@Override |
|
431 |
public boolean cancellationRequested() { |
|
432 |
return m == 0 || downstream.cancellationRequested(); |
|
433 |
} |
|
434 |
}; |
|
435 |
} |
|
436 |
}; |
|
437 |
} |
|
438 |
||
439 |
/** |
|
440 |
* Appends a "slice" operation to the provided DoubleStream. The slice |
|
441 |
* operation may be may be skip-only, limit-only, or skip-and-limit. |
|
442 |
* |
|
443 |
* @param upstream A DoubleStream |
|
444 |
* @param skip The number of elements to skip. Must be >= 0. |
|
445 |
* @param limit The maximum size of the resulting stream, or -1 if no limit |
|
446 |
* is to be imposed |
|
447 |
*/ |
|
448 |
public static DoubleStream makeDouble(AbstractPipeline<?, Double, ?> upstream, |
|
449 |
long skip, long limit) { |
|
450 |
if (skip < 0) |
|
451 |
throw new IllegalArgumentException("Skip must be non-negative: " + skip); |
|
452 |
||
453 |
return new DoublePipeline.StatefulOp<Double>(upstream, StreamShape.DOUBLE_VALUE, |
|
454 |
flags(limit)) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
455 |
Spliterator.OfDouble unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
456 |
Spliterator.OfDouble s, long skip, long limit, long sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
457 |
if (skip <= sizeIfKnown) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
458 |
// Use just the limit if the number of elements |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
459 |
// to skip is <= the known pipeline size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
460 |
limit = limit >= 0 ? Math.min(limit, sizeIfKnown - skip) : sizeIfKnown - skip; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
461 |
skip = 0; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
462 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
463 |
return new StreamSpliterators.UnorderedSliceSpliterator.OfDouble(s, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
464 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
465 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
466 |
@Override |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
467 |
<P_IN> Spliterator<Double> opEvaluateParallelLazy(PipelineHelper<Double> helper, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
468 |
Spliterator<P_IN> spliterator) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
469 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
470 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
471 |
return new StreamSpliterators.SliceSpliterator.OfDouble( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
472 |
(Spliterator.OfDouble) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
473 |
skip, |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
474 |
calcSliceFence(skip, limit)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
475 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
476 |
return unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
477 |
(Spliterator.OfDouble) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
478 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
479 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
480 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
481 |
return new SliceTask<>(this, helper, spliterator, Double[]::new, skip, limit). |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
482 |
invoke().spliterator(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
483 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
484 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
485 |
|
17182 | 486 |
@Override |
487 |
<P_IN> Node<Double> opEvaluateParallel(PipelineHelper<Double> helper, |
|
488 |
Spliterator<P_IN> spliterator, |
|
489 |
IntFunction<Double[]> generator) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
490 |
long size = helper.exactOutputSizeIfKnown(spliterator); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
491 |
if (size > 0 && spliterator.hasCharacteristics(Spliterator.SUBSIZED)) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
492 |
// Because the pipeline is SIZED the slice spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
493 |
// can be created from the source, this requires matching |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
494 |
// to shape of the source, and is potentially more efficient |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
495 |
// than creating the slice spliterator from the pipeline |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
496 |
// wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
497 |
Spliterator<P_IN> s = sliceSpliterator(helper.getSourceShape(), spliterator, skip, limit); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
498 |
return Nodes.collectDouble(helper, s, true); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
499 |
} else if (!StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags())) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
500 |
Spliterator.OfDouble s = unorderedSkipLimitSpliterator( |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
501 |
(Spliterator.OfDouble) helper.wrapSpliterator(spliterator), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
502 |
skip, limit, size); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
503 |
// Collect using this pipeline, which is empty and therefore |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
504 |
// can be used with the pipeline wrapping spliterator |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
505 |
// Note that we cannot create a slice spliterator from |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
506 |
// the source spliterator if the pipeline is not SIZED |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
507 |
return Nodes.collectDouble(this, s, true); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
508 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
509 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
510 |
return new SliceTask<>(this, helper, spliterator, generator, skip, limit). |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
511 |
invoke(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
512 |
} |
17182 | 513 |
} |
514 |
||
515 |
@Override |
|
516 |
Sink<Double> opWrapSink(int flags, Sink<Double> sink) { |
|
19593 | 517 |
return new Sink.ChainedDouble<Double>(sink) { |
17182 | 518 |
long n = skip; |
519 |
long m = limit >= 0 ? limit : Long.MAX_VALUE; |
|
520 |
||
521 |
@Override |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
522 |
public void begin(long size) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
523 |
downstream.begin(calcSize(size, skip, m)); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
524 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
525 |
|
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
526 |
@Override |
17182 | 527 |
public void accept(double t) { |
528 |
if (n == 0) { |
|
529 |
if (m > 0) { |
|
530 |
m--; |
|
531 |
downstream.accept(t); |
|
532 |
} |
|
533 |
} |
|
534 |
else { |
|
535 |
n--; |
|
536 |
} |
|
537 |
} |
|
538 |
||
539 |
@Override |
|
540 |
public boolean cancellationRequested() { |
|
541 |
return m == 0 || downstream.cancellationRequested(); |
|
542 |
} |
|
543 |
}; |
|
544 |
} |
|
545 |
}; |
|
546 |
} |
|
547 |
||
548 |
private static int flags(long limit) { |
|
549 |
return StreamOpFlag.NOT_SIZED | ((limit != -1) ? StreamOpFlag.IS_SHORT_CIRCUIT : 0); |
|
550 |
} |
|
551 |
||
552 |
/** |
|
553 |
* {@code ForkJoinTask} implementing slice computation. |
|
554 |
* |
|
555 |
* @param <P_IN> Input element type to the stream pipeline |
|
556 |
* @param <P_OUT> Output element type from the stream pipeline |
|
557 |
*/ |
|
19218
8e7212b90b81
8022446: Fix serial warnings in java.util.stream
henryjen
parents:
18770
diff
changeset
|
558 |
@SuppressWarnings("serial") |
17182 | 559 |
private static final class SliceTask<P_IN, P_OUT> |
560 |
extends AbstractShortCircuitTask<P_IN, P_OUT, Node<P_OUT>, SliceTask<P_IN, P_OUT>> { |
|
561 |
private final AbstractPipeline<P_OUT, P_OUT, ?> op; |
|
562 |
private final IntFunction<P_OUT[]> generator; |
|
563 |
private final long targetOffset, targetSize; |
|
564 |
private long thisNodeSize; |
|
565 |
||
566 |
private volatile boolean completed; |
|
567 |
||
19593 | 568 |
SliceTask(AbstractPipeline<P_OUT, P_OUT, ?> op, |
17182 | 569 |
PipelineHelper<P_OUT> helper, |
570 |
Spliterator<P_IN> spliterator, |
|
571 |
IntFunction<P_OUT[]> generator, |
|
572 |
long offset, long size) { |
|
573 |
super(helper, spliterator); |
|
19593 | 574 |
this.op = op; |
17182 | 575 |
this.generator = generator; |
576 |
this.targetOffset = offset; |
|
577 |
this.targetSize = size; |
|
578 |
} |
|
579 |
||
580 |
SliceTask(SliceTask<P_IN, P_OUT> parent, Spliterator<P_IN> spliterator) { |
|
581 |
super(parent, spliterator); |
|
582 |
this.op = parent.op; |
|
583 |
this.generator = parent.generator; |
|
584 |
this.targetOffset = parent.targetOffset; |
|
585 |
this.targetSize = parent.targetSize; |
|
586 |
} |
|
587 |
||
588 |
@Override |
|
589 |
protected SliceTask<P_IN, P_OUT> makeChild(Spliterator<P_IN> spliterator) { |
|
590 |
return new SliceTask<>(this, spliterator); |
|
591 |
} |
|
592 |
||
593 |
@Override |
|
594 |
protected final Node<P_OUT> getEmptyResult() { |
|
595 |
return Nodes.emptyNode(op.getOutputShape()); |
|
596 |
} |
|
597 |
||
598 |
@Override |
|
599 |
protected final Node<P_OUT> doLeaf() { |
|
600 |
if (isRoot()) { |
|
601 |
long sizeIfKnown = StreamOpFlag.SIZED.isPreserved(op.sourceOrOpFlags) |
|
602 |
? op.exactOutputSizeIfKnown(spliterator) |
|
603 |
: -1; |
|
604 |
final Node.Builder<P_OUT> nb = op.makeNodeBuilder(sizeIfKnown, generator); |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
605 |
Sink<P_OUT> opSink = op.opWrapSink(helper.getStreamAndOpFlags(), nb); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
606 |
helper.copyIntoWithCancel(helper.wrapSink(opSink), spliterator); |
18770
b71393f8e3e4
8017329: 8b92-lambda regression: TreeSet("a", "b").stream().substream(1).parallel().iterator() is empty
psandoz
parents:
18572
diff
changeset
|
607 |
// There is no need to truncate since the op performs the |
b71393f8e3e4
8017329: 8b92-lambda regression: TreeSet("a", "b").stream().substream(1).parallel().iterator() is empty
psandoz
parents:
18572
diff
changeset
|
608 |
// skipping and limiting of elements |
b71393f8e3e4
8017329: 8b92-lambda regression: TreeSet("a", "b").stream().substream(1).parallel().iterator() is empty
psandoz
parents:
18572
diff
changeset
|
609 |
return nb.build(); |
17182 | 610 |
} |
611 |
else { |
|
612 |
Node<P_OUT> node = helper.wrapAndCopyInto(helper.makeNodeBuilder(-1, generator), |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
613 |
spliterator).build(); |
17182 | 614 |
thisNodeSize = node.count(); |
615 |
completed = true; |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
616 |
spliterator = null; |
17182 | 617 |
return node; |
618 |
} |
|
619 |
} |
|
620 |
||
621 |
@Override |
|
622 |
public final void onCompletion(CountedCompleter<?> caller) { |
|
623 |
if (!isLeaf()) { |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
624 |
Node<P_OUT> result; |
17182 | 625 |
thisNodeSize = leftChild.thisNodeSize + rightChild.thisNodeSize; |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
626 |
if (canceled) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
627 |
thisNodeSize = 0; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
628 |
result = getEmptyResult(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
629 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
630 |
else if (thisNodeSize == 0) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
631 |
result = getEmptyResult(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
632 |
else if (leftChild.thisNodeSize == 0) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
633 |
result = rightChild.getLocalResult(); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
634 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
635 |
result = Nodes.conc(op.getOutputShape(), |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
636 |
leftChild.getLocalResult(), rightChild.getLocalResult()); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
637 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
638 |
setLocalResult(isRoot() ? doTruncate(result) : result); |
17182 | 639 |
completed = true; |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
640 |
} |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
641 |
if (targetSize >= 0 |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
642 |
&& !isRoot() |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
643 |
&& isLeftCompleted(targetOffset + targetSize)) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
644 |
cancelLaterNodes(); |
17182 | 645 |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
646 |
super.onCompletion(caller); |
17182 | 647 |
} |
648 |
||
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
649 |
@Override |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
650 |
protected void cancel() { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
651 |
super.cancel(); |
17182 | 652 |
if (completed) |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
653 |
setLocalResult(getEmptyResult()); |
17182 | 654 |
} |
655 |
||
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
656 |
private Node<P_OUT> doTruncate(Node<P_OUT> input) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
657 |
long to = targetSize >= 0 ? Math.min(input.count(), targetOffset + targetSize) : thisNodeSize; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
658 |
return input.truncate(targetOffset, to, generator); |
17182 | 659 |
} |
660 |
||
661 |
/** |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
662 |
* Determine if the number of completed elements in this node and nodes |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
663 |
* to the left of this node is greater than or equal to the target size. |
18527 | 664 |
* |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
665 |
* @param target the target size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
666 |
* @return true if the number of elements is greater than or equal to |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
667 |
* the target size, otherwise false. |
18527 | 668 |
*/ |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
669 |
private boolean isLeftCompleted(long target) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
670 |
long size = completed ? thisNodeSize : completedSize(target); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
671 |
if (size >= target) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
672 |
return true; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
673 |
for (SliceTask<P_IN, P_OUT> parent = getParent(), node = this; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
674 |
parent != null; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
675 |
node = parent, parent = parent.getParent()) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
676 |
if (node == parent.rightChild) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
677 |
SliceTask<P_IN, P_OUT> left = parent.leftChild; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
678 |
if (left != null) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
679 |
size += left.completedSize(target); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
680 |
if (size >= target) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
681 |
return true; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
682 |
} |
18527 | 683 |
} |
684 |
} |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
685 |
return size >= target; |
18527 | 686 |
} |
687 |
||
688 |
/** |
|
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
689 |
* Compute the number of completed elements in this node. |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
690 |
* <p> |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
691 |
* Computation terminates if all nodes have been processed or the |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
692 |
* number of completed elements is greater than or equal to the target |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
693 |
* size. |
18527 | 694 |
* |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
695 |
* @param target the target size |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
696 |
* @return return the number of completed elements |
18527 | 697 |
*/ |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
698 |
private long completedSize(long target) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
699 |
if (completed) |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
700 |
return thisNodeSize; |
18527 | 701 |
else { |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
702 |
SliceTask<P_IN, P_OUT> left = leftChild; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
703 |
SliceTask<P_IN, P_OUT> right = rightChild; |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
704 |
if (left == null || right == null) { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
705 |
// must be completed |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
706 |
return thisNodeSize; |
18527 | 707 |
} |
18572
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
708 |
else { |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
709 |
long leftSize = left.completedSize(target); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
710 |
return (leftSize >= target) ? leftSize : leftSize + right.completedSize(target); |
53b8b8c30086
8012987: Optimizations for Stream.limit/substream
psandoz
parents:
18527
diff
changeset
|
711 |
} |
18527 | 712 |
} |
713 |
} |
|
17182 | 714 |
} |
715 |
} |