Point lambdafications in java.io

Brian Goetz brian.goetz at oracle.com
Wed Jun 19 07:12:24 PDT 2013

Right, and that's just one problem.  The current implementation of 
CloseableStream is pretty much broken; not only do the methods do not 
return CloseableStream, but close()ing the CS does not have any effect 
on the stream.  So, I think the current CS is just too weak and at the 
same time consumes too much API surface area.  And creating a separate 
bulletproof CS abstraction is more than we can do now.  (And I never 
really liked having any FooableStream interfaces, because they 
invariably proliferate, and you end up in situations where you can you 
get a FooableStream or a BarableStream but you really want a 
FooableBarableStream.  Better not to go there at all.)

But, we can bring AutoCloseable into Stream itself with relatively litle 
pain if we don't demand absolute perfection.  It is fairly easy to 
implement AC in Stream and have close() actually be reflected in the 
behavior of other stream methods with little intrusion and no additional 
runtime performance overhead (we can piggyback on an existing stream 
reuse check.)

Your example about concat() is a good one, but I think it points the 
other way.  My first attempt at incorporating AutoCloseable into Stream 
missed that case.  But if all streams are Closeable, it is possible to 
hit that case in the second round.  With a separate CloseableStream 
abstraction, it will be impractical to ever hit that case.

So I think we have two choices.

  - No close support whatsoever.  Kill existing CloseableStream.  That 
means no use of TWR on IO-backed streams, and no way to release the 
resources except maybe after successful exhaustion of the input.

  - Some reasonable best-effort attempt at "all streams are Closeable", 
like the one I've outlined.

It sounds like your position is "if we can't do it perfectly, don't try?"

On 6/19/2013 6:50 AM, Joe Bowbeer wrote:
> Update:
> Some of my comments were based on the assumption that all streams would
> be Closeable, the way all IO streams are closeable.
> The problem with adding closeable stream separately is that none of the
> closeable streams' stream methods return closeable streams. That, and
> also that there are no closeable primitive streams.
> On Jun 19, 2013 3:36 AM, "Joe Bowbeer" <joe.bowbeer at gmail.com
> <mailto:joe.bowbeer at gmail.com>> wrote:
>     I'm not in favor. As an implementer of custom IO streams, I'm aware
>     of the burden that proper close() implementation adds, as well as
>     the lack of any uses in many contexts. You can't(*) add close and
>     expect best effort to be acceptable. There are unit tests, and close
>     is expected to propagate (right?), e.g., in concat'd and zipped and
>     merged and filtered streams.
>     As Remi points out, this would also require diluting the static
>     analysis checks and editor warnings that are in place to ensure
>     proper use of Closeables. From the programmer's point of view, every
>     Stream would have to be treated as if it were an IO stream.
>     Joe
>     On Jun 18, 2013 6:48 PM, "Brian Goetz" <brian.goetz at oracle.com
>     <mailto:brian.goetz at oracle.com>> wrote:
>         I did a quick look at the code, this would be very easy to
>         implement by piggybacking on top of the existing checking for
>         stream re-use.  Just as
>            Stream s = ...
>            s.forEach(...)
>            s.forEach(...) // throws ISE
>         fails because the stream is being "reused", we can have future
>         stream operations fail with ISE if they are initiated after the
>         stream is closed.  For the example behavior you suggest,
>         probably anything could happen.  But we can make a good-faith
>         effort to prevent future stream operations from proceeding
>         (which, Mike noted, is more than a lot of the existing
>         Autocloseable IO classes do.)
>         On 6/18/2013 12:30 PM, Sam Pullara wrote:
>             I am very much in favor of a way to signal to the stream to
>             relinquish resources so that you don't have to exhaust it to
>             ensure that it is cleaned up. That said, without things like
>             takeWhile() I'm not sure that there are many cases where you
>             can close the stream unless you are in an exception state.
>             What would be the semantics of something like this:
>             Stream stream = list.stream();
>             stream.forEach(o -> stream.close());
>             Sam
>             On Jun 18, 2013, at 9:05 AM, Brian Goetz
>             <brian.goetz at oracle.com <mailto:brian.goetz at oracle.com>> wrote:
>                 The libraries team added the following methods to
>                 java.io <http://java.io> and java.nio, with discussion
>                 on corelibs-dev:
>                 In java.io.BufferedReader:
>                    Stream<String> lines()
>                 In java.nio.Files, static methods for:
>                    CloseableStream<Path> list(Path dir) throws IOException;
>                    CloseableStream<Path> walk(Path start, int maxDepth,
>                 FileVisitOption... options) throws IOException
>                    CloseableStream<Path> walk(Path start,
>                 FileVisitOption... options) throws IOException
>                    CloseableStream<Path> find(Path start,
>                                             int maxDepth,
>                                             BiPredicate<Path,
>                 BasicFileAttributes> matcher,
>                                             FileVisitOption... options)
>                          throws IOException
>                    CloseableStream<String> lines(Path path, Charset cs)
>                 throws IOException
>                 CloseableStream simply extends Stream and AutoCloseable,
>                 making it suitable for use with try-with-resources:
>                 public interface CloseableStream<T> extends Stream<T>,
>                 AutoCloseable {
>                      void close();
>                 }
>                 Should we consider moving AutoCloseable up to Stream and
>                 friends, and get rid of CloseableStream?

More information about the lambda-libs-spec-observers mailing list