On 11 April 2018 at 15:11, Sven Van Caekenberghe <s...@stfx.eu> wrote:
>
>
>> On 11 Apr 2018, at 11:12, Sven Van Caekenberghe <s...@stfx.eu> wrote:
>>
>> How does one modify #atEnd to block ? I suppose you are talking about 
>> StdioStream>>#atEnd ?
>>
>> ^ self peek isNil
>>
>> ?
>
> Still the same question, how do you implement a blocking #atEnd for stdin ?
>
> I have seen your stdio.cs which is indeed needed as the current 
> StdioStream>>#atEnd is bogus for sure.
>
> But that is still a non-blocking one, right ?
>
> Since there is a peekBuffer in StdioStream, why can't that be used ?

I think you've created a chicken-and-egg problem with this question,
but ignoring that for now:


StdioStream>>peek
"Answer what would be returned if the message next were sent to the
receiver. If the receiver is at the end, answer nil.  "

    self atEnd ifTrue: [^ nil ].

    peekBuffer ifNotNil: [ ^ peekBuffer ].

    ^ peekBuffer := self next.



So when we first start the program, i.e. the user hasn't entered any
input yet, and #peek is called:

1. #atEnd returns false because Ctrl-D (or similar) hasn't been
entered (assuming it is non-blocking).
2. peekBuffer is nil because we haven't previously called #peek.
3. The system now blocks on "self next".


Just a reminder: for terminal input the end-of-file isn't reached
until the user explicitly enters the end of file key (Ctrl-D).

So, if there is no buffered input (either none has been entered yet,
or all input has been consumed)

#atEnd (after the patch) calls #primAtEnd:.

At the moment, #primAtEnd: ends up calling the libc function feof(),
which is non-blocking and answers the end-of-file flag for the FILE*.
Since the user hasn't entered Ctrl-D, that's false.

If we want to control iteration over the stream and ensure that we
don't need to do a "stream next == nil" check, then #primAtEnd: is
going to have to peek for the next character, and that means waiting
for the user to enter that character.

In c that is typically done using:

atEnd = ungetc(fgetc(fp), fp);

and fgetc() will block until the user enters something.

> I have run your example testAtEnd.st now, and it works/fails as advertised.

:-)


Cheers,
Alistair

Reply via email to