[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: I/O generic functions



> STREAM-LISTEN is actually not mandatory: you can implement it using
> READ-CHAR-NO-HANG and UNREAD-CHAR.

Yes, I guess you could.  I'm not sure whether that really helps anyone,
though, since a custom method for STREAM-LISTEN would always be faster.

> If people are going to start defining well behaved streams, some
> protocols need to be firmed up.  For instance, if LISTEN is true, must
> READ-CHAR-NO-HANG return a character?  Or is it only that
> READ-CHAR-NO-HANG returns a character or clears the LISTEN condition?
> You can see the difference in the behavior of an encapsulated stream
> with escape characters.  In the one case, LISTEN can just do LISTEN on
> the inside stream, which is presumably fast (e.g. checks some network
> buffer pointers).  If the buffer contains only the start of an escape
> sequence, READ-CHAR-NO-HANG will still not return a character.  In the
> other case, LISTEN must run the entire decoding machinery right away and
> unread any character it produces.  The key decision is whether you want
> LISTEN to be complete or efficient.

An interesting point, but I'm not sure when the eager version of LISTEN
would actually result in a noticeable hang, since the rest of the escape
sequence is going to follow very soon.  Note that page 380 of CLtL says
that 
    On a non-interactive stream, the general rule is that LISTEN is
    true except when at end-of-file.
which implies that delays getting the next physical record from disk or
the next packet from the network are not to be considered significant.
Are you thinking that a terminal user might need to press two keys in
sequence to cause one special character to be input?  In that case, I
think it would be clear that you don't want LISTEN to return true until
all of the necessary keys have been pressed.

> Wouldn't it be better to have just one centralized implementation of
> eof-error-p eof-value handling?  The internal stream methods could obey
> just one protocol for returning EOF which the outer would process
> independently.

Yes, that sounds like a good idea.  Maybe something like the following?


(defconstant THE-EOF-FLAG <some-unique-value>)

(defgeneric STREAM-READ-CHAR (stream)
       (:documentation "Returns either a character or THE-EOF-FLAG."))

(defun READ-CHAR (&optional input-stream (eof-errorp t) eof-value recursive-p)
  (declare (ignore recursive-p))
  (let* ((stream (decode-read-arg input-stream))
	 (value (stream-read-char stream)))
    (if (eq value the-eof-flag)
	(report-eof stream eof-errorp eof-value)
      value)))

(defun report-eof (stream eof-errorp eof-value)
  (if eof-errorp
      (error 'end-of-file :stream stream)
    eof-value))