Ewald wrote:
And what with non-blocking pipes pipes? Wait for a *some* period
until you get all data? It is up to the programmer to do this INHO.

If you want to get partial data (instead of waiting until all requested data is available) you should just use TStream.Read instead of TStream.ReadBuffer. Then it's indeed up to the programmer to handle this.

All existing usage of ReadBuffer right now works only if you get all the data in a single Read call (which translates to a single read syscall on Linux, as far as I see), otherwise it fails with exception. That's just wrong behavior for a ReadBuffer IMHO.

Also, if you would enforce this behaviour on all kinds of streams,
you might (`will`, actually) get unexpected performance drops...

I don't see why you would get any performance drop. If you're lucky and a single Read call is all you need, then the speed is the same as current implementation, since the 1st check "if Read(Buffer,Count)<Count then" will return false and we will not call Read again.

Besides, we're talking about correctness here. And TStream.ReadBuffer is non-virtual and must be suitable for all TStream descedants, handling whatever virtual TStream.Read does.



For example: on Linux, TFileStream.Read calls fpRead which is a
system call, and it definitely can return less than requested
amount of bytes, and it doesn't mean that stream ended. (See e.g.
Libc docs:
http://www.gnu.org/software/libc/manual/html_mono/libc.html#I_002fO-Primitives
: "If read returns at least one character, there is no way you can
tell whether end-of-file was reached. But if you did reach the end,
the next read will return zero. ") So if you use TFileStream with
ReadBuffer, your code is working purely by accident right now...


But if you work with a blocking fd (which, for example, a TFileStream
uses IIRC) you will always get your data. If there is more data to be
read(), but it would take time, it simply takes time. The only case
where zero is returned, is IIRC (like you quoted) when the end of the
`fd` (e.g. pipe, socket, file) is reached on *blocking
filedescriptors*.

Yes, zero is returned only if stream ends. But a result that is non-zero, but still less than requested Count, doesn't tell you if the stream ends. The whole point is whether ReadBuffer should take this into account.

FYI: I've never had the problem of a `partial read` (e.g.
SomeStream.Read(50) returning 36 or something) on linux, osx and
windows; so perhaps you have exposed some bug in an obscure TStream
descendant?


Reproducing this behavior proved to be difficult, but I definitely observed it with TFileStream on Linux.

And, even if it would accidentally work for some streams, that's not a solution. Like I mentioned, TStream.ReadBuffer is non-virtual and must be suitable for every TStream.

Michalis
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to