lambda-dev Digest, Vol 43, Issue 39
Howard Lovatt
howard.lovatt at gmail.com
Sun Jun 23 17:06:31 PDT 2013
I did hold the view that implementing AutoCloseable was a good idea, so I
tried it in my own code (I have my own Stream library). However for me it
didn't work out well because the IDE complained so much about lack of try
blocks (that in my case were all unnecessary because of the way I
implemented the stream - see below). Therefore I would in hindsight propose
no AutoCloaseable, so that you write:
try (SomeResource r = ...) {
r.stream()....;
}
As an implementation note, if AutoCloseable is implemented then I found it
necessary to create the resource lazily to eliminate resource leaks from
code like:
new SomeResource( ... ).stream().map(
callToMethodThatReturnsMapperButAlsoThrowsAnException() )...collect( ... );
The problem above is that even if collect() has a try block the resource is
grabbed by the new and then when the exception is thrown by
callToMethodThatReturnsMapperButAlsoThrowsAnException() the resource isn't
released unless the whole line is inside a try block. Instead I grab the
resource lazily:
Streams.from( () -> new SomeResource( ... ) ).map(
callToMethodThatReturnsMapperButAlsoThrowsAnException() )...collect( ... );
Which works because the resource isn't grabbed at all if
callToMethodThatReturnsMapperButAlsoThrowsAnException() throws an exception.
On 24 June 2013 06:45, Cleber Muramoto <cleber at nightcoders.com.br> wrote:
> I'd rather have Stream implementing AutoCloseable. In my humble opinion,
> .Net got it right by making IEnumerable extend IDisposable. One can work
> with the same 'contracts' and does not need to bother (from a pure code
> perspective) if the stuff is coming from the memory or from the database or
> from anywhere else.
>
> The good:
>
> -No need for another indirection
> -Code more concise
>
> The bad:
>
> -Ide's complaing that you're leaking a resource if you do not wrap every
> stream in a try(...)
> -May induce 'generic' programing with thousands of unnecessary try(..){ }
> blocks (the penalty however, is negligible comparing to consuming the
> stream itself)
>
> Anyway, I would like the API to be consistent enough to support use cases
> beyond (java) I/O or SQL ops, but for anything that might require explicit
> resource release - either to avoid resource leaks or so release cache-like
> data structures after a unit of work is done.
>
> Maybe your proposal could be achieved via composition as well, at the
> expense of delegating every call to a wrapped downstream.
>
> interface Stream<T>{
>
> //...
>
> default ACS<T> asCloseable(Callable<Void> onClose){
> return new ACS(this,onClose);
> }
>
> }
>
> final class ACS<T> implements Stream<T>,AutoCloseable{
>
> Callable<Void> onClose;
> Stream<T> del;
>
> //delegates everyhing to del
>
> public void close(){
> try{
> onClose.call();
> }catch(... e){
> throw RTE(e);
> }
> }
>
> }
>
> While your Scope interface makes it clear that one is working with
> resources that must be manually released, I don't like the extra-verbosity.
> :) I think, however, that it might make the work easier, e.g., for
> implementing stuff like generators , in the future:
>
> IntStream getAllIds(){
>
> try(ResultSet rs = ...){
> while(rs.next()){
> yield rs.getInt(1);
> }
> }
> }
>
> (This could be ambiguous: rs.close should be called once stream.close is
> called or when the loop is over?)
>
> IntStream getAllIds(Scope s){
> ResultSet rs = ...;
>
> s.onClose(()->{rs.close();});
>
> while(rs.next()){
> yield rs.getInt(1);
> }
> }
>
> (Not ambiguous-but "feels like" there's a resource leak!)
>
>
>
> On Fri, Jun 21, 2013 at 4:00 PM, <lambda-dev-request at openjdk.java.net
> >wrote:
>
> >
> > 10. Utilities of auto close (Zhong Yu)
> >
> >
> > ----------------------------------------------------------------------
> >
> >
> > Message: 10
> > Date: Fri, 21 Jun 2013 09:41:48 -0500
> > From: Zhong Yu <zhong.j.yu at gmail.com>
> > Subject: Utilities of auto close
> > To: "lambda-dev at openjdk.java.net" <lambda-dev at openjdk.java.net>
> > Message-ID:
> > <CACuKZqEZ05Pt9c3ZQm716EiP_G-GSk=
> > N6yAEU8w4++g9Dozn-g at mail.gmail.com>
> > Content-Type: text/plain; charset=ISO-8859-1
> >
> > EG is discussing the issue of closing a Stream that ties to IO
> > resources, and I'd like to throw in my 2 cents.
> >
> > Background: some new IO methods return Stream of things, for example
> >
> > class Files
> > /** return a stream of entries in the dir */
> > static Stream<Path> list(Path dir);
> >
> > The problem is some IO resources are tied up and they need to be freed
> > as soon as the Stream is no longer used.
> >
> > The current solution is
> >
> > interface CloseableStream<T> extends Stream<T>, AutoCloseable
> >
> > static CloseableStream<Path> list(Path dir);
> >
> > EG is discussing an alternative that makes all Streams AutoCloseable
> >
> > interface Stream<T> extends AutoCloseable
> >
> > Some disagree with that approach, since most Streams do not need to be
> > closed.
> >
> > ==
> > My proposal:
> >
> > It's better to move the business of close() away from Stream to some
> > surrounding constructs. For example:
> >
> > try(Scope scope = Scope.newInstance())
> > {
> > Stream<Path> entries = Files.list(scope, dir);
> > }
> >
> > interface Scope extends AutoCloseable
> > {
> > void onClose(Runnable action);
> >
> > void close();
> > }
> >
> > static Stream<Path> list(Scope scope, Path dir)
> > {
> > ...
> > scope.onClose( ()->{ free resources } );
> > ...
> > }
> >
> >
> > Scope provides generic destructor-like functionality, orthogonal to
> > resource types.
> >
> > Zhong Yu
> >
> >
> > End of lambda-dev Digest, Vol 43, Issue 39
> > ******************************************
> >
>
>
--
-- Howard.
More information about the lambda-dev
mailing list