Hello!

Thanks for review! Updated webrev:
http://cr.openjdk.java.net/~tvaleev/webrev/8147505/r2/
Removed redundant test and added a comment.

With best regards,
Tagir Valeev.

PS> Hi Tagir,

PS> StreamCloseTest.java
PS> —

PS>  181         try(Stream<Integer> s = countTo(100).stream()) {
PS>  182             s.map(x -> x).forEach(i -> {});
PS>  183             checkISE(() -> s.onClose(() -> fail("2")));
PS>  184         }

PS> We don’t need this one, it’s redundant. The other performing the
PS> s.close() is i think useful because i don’t recall it being tested
PS> in other places like this, plus it also tests the idempotent
PS> behaviour, perhaps worth a comment on this in the test.

PS> Otherwise, +1

PS> Again, i will handle in bulk with your other fixes.

PS> Many thanks,
PS> Paul.

>> On 23 Jan 2016, at 11:38, Tagir F. Valeev <amae...@gmail.com> wrote:
>> 
>> Hello!
>> 
>> Here's a webrev:
>> http://cr.openjdk.java.net/~tvaleev/webrev/8147505/r1/
>> 
>> I just added a check in AbstractPipeline.onClose and the corresponding
>> unit-test. To me it seems that no documentation corrections are
>> necessary, because "onClose" is already documented that it's
>> an intermediate operation:
>> 
>> http://download.java.net/jdk9/docs/api/java/util/stream/BaseStream.html#onClose-java.lang.Runnable-
>> 
>> Also it's already documented:
>> 
>>> A stream should be operated on (invoking an intermediate or terminal
>>> stream operation) only once. This rules out, for example, "forked"
>>> streams, where the same source feeds two or more pipelines, or
>>> multiple traversals of the same stream. A stream implementation may
>>> throw IllegalStateException if it detects that the stream is being
>>> reused.
>> 
>> http://download.java.net/jdk9/docs/api/java/util/stream/Stream.html
>> 
>> So this already implies that invoking intermediate operation "onClose"
>> after stream terminal operation is not allowed and may throw
>> IllegalStateException.
>> 
>> Please review!
>> 
>> With best regards,
>> Tagir Valeev.
>> 
>> TFV> Seems that my original letter sounds confusing due to my bad English.
>> TFV> Every occurrence of "idempotent" should be read as "not idempotent".
>> TFV> Sorry for this!
>> 
>> PS>> We did not bother to throw ISEs from parallel/sequence/onClose
>> PS>> primarily because they return “this” and they are kind of
>> PS>> harmless, but the undefined behaviour you point out could be shut
>> PS>> down without much concern for backwards compatibility. We can
>> PS>> modify them to check whether they have been linked or consumed
>> PS>> (while not updating the previous stage).
>> 
>> PS>> Wanna log an issue?
>> 
>> TFV> Sure:
>> TFV> https://bugs.openjdk.java.net/browse/JDK-8147505
>> 
>> TFV> Thanks,
>> TFV> Tagir Valeev.
>> 
>> PS>> Thanks,
>> PS>> Paul.
>> 
>> 
>>>>> On 15 Jan 2016, at 05:35, Tagir F. Valeev <amae...@gmail.com> wrote:
>>>>> 
>>>>> Hello!
>>>>> 
>>>>> Current documentation for BaseStream.onClose() does not specify
>>>>> explicitly how the stream would behave if additional close handlers
>>>>> are registered after the stream is consumed or even closed. The
>>>>> implementation actually allows registering the additional close
>>>>> handlers after consumption or closure and close() method is
>>>>> idempotent: newly registered handlers are perfectly called:
>>>>> 
>>>>> Stream<String> s = Stream.of("content");
>>>>> s = s.onClose(() -> System.out.println("A"));
>>>>> s.forEach(System.out::println);
>>>>> s = s.onClose(() -> System.out.println("B"));
>>>>> s.close(); // prints A and B
>>>>> s = s.onClose(() -> System.out.println("C"));
>>>>> s.close(); // prints C
>>>>> 
>>>>> (removing "s =" produces the same result).
>>>>> 
>>>>> I think if such behavior is intended, it should be explicitly noted in
>>>>> the specification, as third-party implementations of BaseStream
>>>>> interface should provide consistent behavior. Or at least it should be
>>>>> noted that some BaseStream implementations may have idempotent close()
>>>>> method, so the derived AutoCloseable objects (which own the BaseStream
>>>>> object) should be aware about this behavior and provide idempotent
>>>>> close() method as well. Without knowing this one may write:
>>>>> 
>>>>> class MyObject implements AutoCloseable {
>>>>> private BaseStream<?, ?> s;
>>>>> 
>>>>> public MyObject(BaseStream<?, ?> s) {
>>>>>   this.s = s;
>>>>> }
>>>>> 
>>>>> @Override
>>>>> public void close() throws Exception {
>>>>>   if(s != null) {
>>>>>     s.close();
>>>>>     s = null;
>>>>>   }
>>>>> }
>>>>> }
>>>>> 
>>>>> Such code closes the stream only once, so newly registered handlers
>>>>> will not be called if MyObject::close is called the second time.
>>>>> 
>>>>> However, to my opinion the current behavior is weird and should be
>>>>> changed in order not to allow registering new close handles (throwing
>>>>> IllegalStateException) when the stream is already closed, or even
>>>>> better when the stream is linked/consumed. As far as I know currently
>>>>> in JDK close handlers are registered only for non-consumed stream, so
>>>>> such change would not break existing JDK code (though may break some
>>>>> strange third party code). It should be noted that AutoCloseable
>>>>> interface discourages idempotent close() methods (though not forbids
>>>>> them).
>>>>> 
>>>>> What do you think?
>>>>> 
>>>>> With best regards,
>>>>> Tagir Valeev.
>>>>> 
>> 

Reply via email to