RFR(m) 2: 8072722: add stream support to Scanner

Xueming Shen xueming.shen at oracle.com
Wed Sep 16 15:56:34 UTC 2015

On 9/16/15 8:43 AM, Xueming Shen wrote:
> On 9/15/15 9:48 PM, Stuart Marks wrote:
>> On 9/10/15 2:12 PM, Xueming Shen wrote:
>>> I think it might be a "nice to have" for a "fail-fast" effort after 
>>> the the
>>> consumer consumed/accepted the result (the second check), but isn't 
>>> it a bug
>>> for the consumer to accept any result if there is CME condition 
>>> occurred
>>> already?
>> I'm not sure which spliterator we're talking about at this point, but 
>> the issue is similar between them. Prior to calling the consumer's 
>> accept() method, in FindSpliterator, the modCount has previously been 
>> asserted to be equal to expectedCount. In TokenSpliterator, the 
>> expectedCount is refreshed from the modCount immediately prior to 
>> calling accept(). (This is done because advancing the spliterator in 
>> this case increments the modCount.)
>> In both spliterators, then, the expectedCount should be equal to the 
>> modCount immediately prior to the call to accept(). Also in both 
>> spliterators, the modCount and expectedCount are compared immediately 
>> after accept(), and if they aren't equal, CME is thrown.
> For both spliterators, particularly the token() method. The check 
> after the accept() method is fine
> (as you suggested below, it guards against the wrong doing by the user 
> code inside the accept()).
> I'm talking about the check "immediately" prior to the call to 
> accept(). It will not function after the
> modCount tips over to the negative int value, because the 
> "expectedCount >=0" check.
> Consider the use scenario that the Scanner is on top of an endless 
> input stream, you have a token
> stream on top of it. The check before the "accept(token" will not be 
> performed until the
> expectedCount/modCount tips back to positive value again from the 
> negative, then off, then on...
> During the off period (it will take a while from negative back to 
> positive), the stream will just work
> fine to feed the accept() the "next" token even if there is another 
> thread keeps "stealing" tokens from
> the same scanner, if the timing is right.  Looks like not really a 
> "fail-fast" in this scenario.
> This can be "easily" addressed, if you have a separate boolean field 
> such as "initlized". The code
> can look like below in tryAdvance(...)
>     if (!initialize) {
>         expectedCount = modCount;
     ---> initialized = true;

>     }
>     if (expectedCount != modCount) {
>         throw new CME();
>     }
>     ...
> Well, if you think this is an unlikely use scenario and the intention 
> of the check/guard here
> is mainly to prevent the wrong doing within the pipe operation, then 
> it might not worth the
> extra field, and I'm fine with the latest webrev.
> -Sherman
>> What this guards against is the accept() method -- really, one of the 
>> application's lambdas that's been passed to a pipeline operation -- 
>> modifying the state of the scanner. This only really works in a 
>> sequential stream, but it's all we've got. (In a parallel stream, I 
>> think the element is buffered somewhere and is handed to another 
>> thread. If that other thread attempts to modify the scanner's state, 
>> all bets are off because of memory visibility issues.)
>> Anyway, at least for sequential streams, this check does properly 
>> guard against the case where somebody modifies the scanner's state 
>> from within a pipeline operation. There are tests for this too; see 
>> ScanTest.streamComodTest().

More information about the core-libs-dev mailing list