Stream is AutoCloseable, Stream.onClose

Remi Forax forax at univ-mlv.fr
Thu Jun 20 11:48:09 PDT 2013


On 06/20/2013 08:18 PM, Brian Goetz wrote:
> FWIW, the closest analogue to "onClose" in the current API is 
> "parallel", which modifies execution characteristics of the current 
> stream (whether it does this mutatively or functionally is a detail).
>
> Perhaps a good analogy would be: what would you call a "register a 
> close hook" method on a builder object?  Because Stream is kind of 
> like a builder.  I am not sure the onClose(closeAction) is all that 
> confusing in the context of a builder; its not a method declaration, 
> and almost no user will ever implement Stream directly, so I'm not 
> sure the confusion is all that bad?

I agree with Joe, onClose is often use for a callback (node.js and Dart 
are full of them),
I think I prefer finallyClose(AutoCloseable).

cheers,
Rémi

>
> On 6/20/2013 2:10 PM, Joe Bowbeer wrote:
>> I like the benefits, though I think the onClose name is confusing.
>>
>> In many frameworks, the onError/onExit/onEvent naming style is reserved
>> for method names in callback interfaces.  It is the prevalent convention
>> currently.  So I'd expect onClose() to be the method that is called-back
>> upon closing.
>>
>> The method name that is needed for this wrapping purpose should be
>> something more imperative, possibly mentioning its function as a "close"
>> guard.
>>
>> Some ideas below:
>>
>> .autoclose(ac)
>> .autoclosing(ac)
>>
>> .closeableStream(ac)
>>
>> --Joe
>>
>>
>> On Thu, Jun 20, 2013 at 8:22 AM, Brian Goetz <brian.goetz at oracle.com
>> <mailto:brian.goetz at oracle.com>> wrote:
>>
>>     Paul, this looks great.  I love that we can get rid of
>>     CloseableStream and DelegatingStream (two of the last remaining
>>     top-level API warts), and efficiently incorporate resource release
>>     in a predictable manner.
>>
>>
>>
>>
>>
>>     On 6/20/2013 11:17 AM, Paul Sandoz wrote:
>>
>>         Hi,
>>
>>         Having another go at this...
>>
>>         The current solution of resource management for Stream is poor
>>         (as previously mentioned):
>>
>>         1) CloseableStream/__DelegatingStream add a lot of API 
>> surface area.
>>
>>         2) Operations on CloseableStream do not return a 
>> CloseableStream.
>>
>>         3) try-with-resources always needs to be used with the
>>         CloseableStream since the Stream itself has no closeable 
>> semantics.
>>
>>         4) Stream.concat fails to propagate the closing
>>
>>
>>         If Stream extends from AutoCloseable we can address the first 3
>>         issues. In fact it can be addressed with just a close method but
>>         it is awkward to transform that into an AutoCloseable for use
>>         with try-with-resources: try (AutoCloseable ac = () ->
>>         s.close()) { … }
>>
>>         A negative point is it is no longer clear whether a stream
>>         should be closed or not, which is anyway the case for issues
>>         2/3/4. However, i don't think that should stop us trying to
>>         improve the general situation, it's not gonna be perfect but i
>>         think we can do better than what we currently have [*].
>>
>>
>>         Issue 4 can be addressed by adding a
>>         Stream.onClose(AutoCloseable ac) method.
>>
>>         Stream s = ...
>>         s = s.onClose(a).filter(...).__onClose(b).
>>         s.close(); // b is called, then a is called
>>         s.toArray(); // throws ISE
>>
>>         Stream s = ...
>>         s = s.onClose(a).onClose(b).
>>         s.close(); // b is called, then a is called
>>         s.toArray(); // throws ISE
>>
>>         The Stream.concat implementation becomes:
>>
>>                   Stream<T> cs = (a.isParallel() || b.isParallel())
>>                          ? StreamSupport.parallelStream(__split)
>>                          : StreamSupport.stream(split);
>>
>>                   return cs.onClose(() -> { a.close(); b.close(); } ) //
>>         ignoring exception handling to be brief
>>
>>
>>         The Stream.close/onClose methods enable us to specify more
>>         precisely the behaviour of Stream.close, the order in which
>>         calls to close on AutoClosable instances passed to onClose
>>         occur, and what happens if AutoCloseable.close throws an 
>> exception.
>>
>>
>>         Of course it is possible to do silly things like this:
>>
>>             s = s.conClose(a).filter(...).__onClose(s).
>>
>>         but we could detect if s is stage in the pipeline and throw 
>> an IAE.
>>
>>
>>         FWIW Stream.close/onClose is easy to implement efficiently.
>>
>>         Paul.
>>
>>         [*] The JDK world is murky, see ByteArrayInputStream.close:
>>
>>               /**
>>                * Closing a <tt>ByteArrayInputStream</tt> has no effect.
>>         The methods in
>>                * this class can be called after the stream has been
>>         closed without
>>                * generating an <tt>IOException</tt>.
>>                * <p>
>>                */
>>               public void close() throws IOException {
>>               }
>>
>>



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