mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8075939: Stream.flatMap() causes breaking of short-circuiting of terminal operations
Reviewed-by: forax, smarks
This commit is contained in:
parent
8c39e16731
commit
e1e9023545
6 changed files with 262 additions and 51 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -40,7 +40,6 @@ import java.util.function.DoubleToIntFunction;
|
|||
import java.util.function.DoubleToLongFunction;
|
||||
import java.util.function.DoubleUnaryOperator;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.LongPredicate;
|
||||
import java.util.function.ObjDoubleConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -265,6 +264,12 @@ abstract class DoublePipeline<E_IN>
|
|||
@Override
|
||||
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
|
||||
return new Sink.ChainedDouble<Double>(sink) {
|
||||
// true if cancellationRequested() has been called
|
||||
boolean cancellationRequestedCalled;
|
||||
|
||||
// cache the consumer to avoid creation on every accepted element
|
||||
DoubleConsumer downstreamAsDouble = downstream::accept;
|
||||
|
||||
@Override
|
||||
public void begin(long size) {
|
||||
downstream.begin(-1);
|
||||
|
@ -273,11 +278,27 @@ abstract class DoublePipeline<E_IN>
|
|||
@Override
|
||||
public void accept(double t) {
|
||||
try (DoubleStream result = mapper.apply(t)) {
|
||||
// We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
|
||||
if (result != null)
|
||||
result.sequential().forEach(i -> downstream.accept(i));
|
||||
if (result != null) {
|
||||
if (!cancellationRequestedCalled) {
|
||||
result.sequential().forEach(downstreamAsDouble);
|
||||
}
|
||||
else {
|
||||
var s = result.sequential().spliterator();
|
||||
do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsDouble));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancellationRequested() {
|
||||
// If this method is called then an operation within the stream
|
||||
// pipeline is short-circuiting (see AbstractPipeline.copyInto).
|
||||
// Note that we cannot differentiate between an upstream or
|
||||
// downstream operation
|
||||
cancellationRequestedCalled = true;
|
||||
return downstream.cancellationRequested();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue