Skip to content
This repository was archived by the owner on Jul 17, 2024. It is now read-only.
/ jdk22u Public archive

Commit 64b4949

Browse files
Viktor KlangAlan Bateman
Viktor Klang
authored and
Alan Bateman
committed
8328316: Finisher cannot emit if stream is sequential and integrator returned false
Reviewed-by: alanb Backport-of: ab28045d7785d948b2bce685f06043e8217961f4
1 parent bcf0d25 commit 64b4949

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

src/java.base/share/classes/java/util/stream/GathererOp.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -142,6 +142,7 @@ static final class GatherSink<T, A, R> implements Sink<T>, Gatherer.Downstream<R
142142
private final Integrator<A, T, R> integrator; // Optimization: reuse
143143
private A state;
144144
private boolean proceed = true;
145+
private boolean downstreamProceed = true;
145146

146147
GatherSink(Gatherer<T, A, R> gatherer, Sink<R> sink) {
147148
this.gatherer = gatherer;
@@ -173,12 +174,12 @@ public void accept(T t) {
173174

174175
@Override
175176
public boolean cancellationRequested() {
176-
return cancellationRequested(proceed);
177+
return cancellationRequested(proceed && downstreamProceed);
177178
}
178179

179180
private boolean cancellationRequested(boolean knownProceed) {
180181
// Highly performance sensitive
181-
return !(knownProceed && (!sink.cancellationRequested() || (proceed = false)));
182+
return !(knownProceed && (!sink.cancellationRequested() || (downstreamProceed = false)));
182183
}
183184

184185
@Override
@@ -194,12 +195,12 @@ public void end() {
194195

195196
@Override
196197
public boolean isRejecting() {
197-
return !proceed;
198+
return !downstreamProceed;
198199
}
199200

200201
@Override
201202
public boolean push(R r) {
202-
var p = proceed;
203+
var p = downstreamProceed;
203204
if (p)
204205
sink.accept(r);
205206
return !cancellationRequested(p);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2024, 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
import java.util.List;
24+
import java.util.stream.Collectors;
25+
import java.util.stream.Gatherer;
26+
27+
import org.junit.jupiter.api.Test;
28+
import static org.junit.jupiter.api.Assertions.*;
29+
import static org.junit.jupiter.api.Assumptions.*;
30+
31+
/**
32+
* @test
33+
* @bug 8328316
34+
* @summary Testing Gatherer behavior under short circuiting
35+
* @enablePreview
36+
* @run junit GathererShortCircuitTest
37+
*/
38+
39+
public class GathererShortCircuitTest {
40+
@Test
41+
public void mustBeAbleToPushFromFinisher() {
42+
Integer expected = 8328316;
43+
List<Integer> source = List.of(1,2,3,4,5);
44+
45+
Gatherer<Integer, ?, Integer> pushOneInFinisher =
46+
Gatherer.of(
47+
(_, element, downstream) -> false,
48+
(_, downstream) -> downstream.push(expected)
49+
);
50+
51+
var usingCollect =
52+
source.stream().gather(pushOneInFinisher).collect(Collectors.toList());
53+
var usingBuiltin =
54+
source.stream().gather(pushOneInFinisher).toList();
55+
var usingCollectPar =
56+
source.stream().parallel().gather(pushOneInFinisher).collect(Collectors.toList());
57+
var usingBuiltinPar =
58+
source.stream().parallel().gather(pushOneInFinisher).toList();
59+
60+
assertEquals(List.of(expected), usingCollect);
61+
assertEquals(List.of(expected), usingBuiltin);
62+
assertEquals(List.of(expected), usingCollectPar);
63+
assertEquals(List.of(expected), usingBuiltinPar);
64+
}
65+
}

0 commit comments

Comments
 (0)