--- /dev/null 2013-02-14 00:07:37.184020992 -0500
+++ new/src/share/classes/java/util/stream/ForEachUntilOp.java 2013-02-21 14:11:05.000000000 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.stream;
+
+import java.util.Objects;
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+/**
+ * A {@code TerminalOp} that evaluates a stream pipeline and sends the output into a {@code TerminalSink}, attempting
+ * to stop early if some external termination condition is reached.
+ *
+ * @apiNote
+ * The termination condition is an externally-imposed criteria, and is useful for problems like "find the best
+ * answer that can be found in ten seconds", "search until you find an answer at least as good as X", etc. It is not
+ * designed to provide content-based cancellation, such as "process elements until you find one which matches
+ * a given criteria."
+ *
+ *
There is no guarantee that additional elements will not be processed after the termination criteria has
+ * transpired. For example, a termination criteria of {@code resultSet.size() > TARGET} does not guarantee that the
+ * result set will receive no more than {@code TARGET} elements, but instead that @{code ForEachUntilOp} will attempt
+ * to stop after {@code TARGET} elements have been placed in the result set.
+ *
+ * @param The output type of the stream pipeline
+ * @since 1.8
+ */
+class ForEachUntilOp extends ForEachOp implements TerminalOp {
+ public ForEachUntilOp(TerminalSink sink, StreamShape shape) {
+ super(sink, shape);
+ }
+
+ /**
+ * Construct a {@code ForEachUntilOp} that reads from a {@code Stream} and sends the stream output to
+ * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input
+ * should be sent
+ * @param consumer The {@code Consumer} to send stream output to
+ * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once
+ * it returns @{code true} the first time, it must continue to return {@code true} for all future
+ * invocations
+ * @param The type of the stream elements
+ */
+ public static ForEachUntilOp make(final Consumer super T> consumer, BooleanSupplier until) {
+ Objects.requireNonNull(consumer);
+ return new ForEachUntilOp<>(new VoidTerminalSink() {
+ @Override
+ public void accept(T t) {
+ consumer.accept(t);
+ }
+
+ @Override
+ public boolean cancellationRequested() {
+ return until.getAsBoolean();
+ }
+ }, StreamShape.REFERENCE);
+ }
+
+ /**
+ * Construct a {@code ForEachUntilOp} that reads from an {@code IntStream} and sends the stream output to
+ * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input
+ * should be sent
+ * @param consumer The {@code Consumer} to send stream output to
+ * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once
+ * it returns @{code true} the first time, it must continue to return {@code true} for all future
+ * invocations
+ */
+ public static ForEachUntilOp make(final IntConsumer consumer, BooleanSupplier until) {
+ Objects.requireNonNull(consumer);
+ return new ForEachUntilOp<>(new VoidTerminalSink.OfInt() {
+ @Override
+ public void accept(int i) {
+ consumer.accept(i);
+ }
+
+ @Override
+ public boolean cancellationRequested() {
+ return until.getAsBoolean();
+ }
+ }, StreamShape.INT_VALUE);
+ }
+
+ /**
+ * Construct a {@code ForEachUntilOp} that reads from a {@code LongStream} and sends the stream output to
+ * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input
+ * should be sent
+ * @param consumer The {@code Consumer} to send stream output to
+ * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once
+ * it returns @{code true} the first time, it must continue to return {@code true} for all future
+ * invocations
+ */
+ public static ForEachUntilOp make(final LongConsumer consumer, BooleanSupplier until) {
+ Objects.requireNonNull(consumer);
+ return new ForEachUntilOp<>(new VoidTerminalSink.OfLong() {
+ @Override
+ public void accept(long i) {
+ consumer.accept(i);
+ }
+
+ @Override
+ public boolean cancellationRequested() {
+ return until.getAsBoolean();
+ }
+ }, StreamShape.LONG_VALUE);
+ }
+
+ /**
+ * Construct a {@code ForEachUntilOp} that reads from a {@code DoubleStream} and sends the stream output to
+ * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input
+ * should be sent
+ * @param consumer The {@code Consumer} to send stream output to
+ * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once
+ * it returns @{code true} the first time, it must continue to return {@code true} for all future
+ * invocations
+ */
+ public static ForEachUntilOp make(final DoubleConsumer consumer, BooleanSupplier until) {
+ Objects.requireNonNull(consumer);
+ return new ForEachUntilOp<>(new VoidTerminalSink.OfDouble() {
+ @Override
+ public void accept(double i) {
+ consumer.accept(i);
+ }
+
+ @Override
+ public boolean cancellationRequested() {
+ return until.getAsBoolean();
+ }
+ }, StreamShape.DOUBLE_VALUE);
+ }
+
+ @Override
+ public int getOpFlags() {
+ return StreamOpFlag.IS_SHORT_CIRCUIT | StreamOpFlag.NOT_ORDERED;
+ }
+}