2018-04-11 17:02 GMT+02:00 Sven Van Caekenberghe <s...@stfx.eu>: > > > > On 11 Apr 2018, at 16:36, Sven Van Caekenberghe <s...@stfx.eu> wrote: > > > > I can make your example, using the Zn variants, work with the following > change: > > > > StdioStream>>#atEnd > > ^ peekBuffer isNil or: [ (peekBuffer := self next) isNil ] > > Argh, make that > > atEnd > ^ peekBuffer isNil and: [ (peekBuffer := self next) isNil ] >
But discussion exactly about "self next isNil": how to avoid it. > > but I am still testing, this is probably not the final answer/solution. > > > Which is a literal implementation of your statement that you can only > know that you are atEnd by reading (and thus waiting/blocking) and checking > for nil, which seems logical to me, given the fact that you *are* waiting > for user input. > > > > BTW, at least on macOS you have to enter ctrl-D (^D) on a separate line, > I am not sure how relevant that is, but that is probably another argument > that stdin is special (being line-buffered by the OS, EOF needing to be on > a separate line). > > > > And FWIW, I have been writing networking code in Pharo for years, and I > have never had issues with unclear semantics of these primitives (#atEnd, > #next, #peek) on network streams, either the classic SocketStream or the > Zdc* streams (TLS or not). That is why I think we have to be careful. > > > > That being said, it is important to continue this discussion, I find it > very interesting. I am trying to write some test code using stdin myself, > to better understand the topic. > > > >> On 11 Apr 2018, at 16:06, Alistair Grant <akgrant0...@gmail.com> wrote: > >> > >> 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 > > > > >