[phobos] Improvement of stream

SHOO zan77137 at nifty.com
Tue Jul 6 04:04:14 PDT 2010


Thanks for your reply.

Perhaps Stream which you imagine and Stream which I imagine are 
different. Stream which I imagine corresponds approximately to File and 
Socket and so on.
The name may be bad. And I think  it to be close in Handle which you say.
Even if the name is Handle, Resource or Device, etc. , I will accept it. 
(For convenience, in my sentence of this time, I unify it in Stream.)
Addition template to input device would bring general versatility to 
Ranges for streaming.

Please take it into consideration.


(2010/07/05 14:37), Andrei Alexandrescu wrote:
> Hello,
>
>
> I've been looking over the streaming proposal. Allow me to make a few
> comments:
>
> - The input ranges _are_ intended to be input streams, and the output
> ranges _are_ intended to be output streams. If they don't fulfill that
> purpose, they should be changed (instead of adding new categories).
>

Firstly I said, The input ranges are not intended to be input streams 
which I imagine. The input ranges are more high level interface that 
_use_ streams.

> - Input streams have the read primitive. What is wrong with an input
> range of ubyte[]? Then accessing front() gives you a buffer and popFront
> reads in a new buffer.
>

For example, reading of binary data from Stream for initialization of 
following struct data is like a nightmare:
struct S{
     int a;
     ubyte[] b;
     double c;
}

For this initialization, you will read data that has different size 
least 4 times.
You might try following code:

File f;
... = f.byChunk(4);
... = f.byChunk(size_t.sizeof);
... = f.byChunk(s.b.length);
... = f.byChunk(8);

I hardly see it effectively. And I think we should become careful to 
complicate Range more than current one.

> - What does flush() do for input streams?
>

I don't think deeply. File.rewind() may correspond to this.

> - I don't think close() is a good primitive for an input stream. An
> input stream should originate in a connection handle, and it's the
> handle, not the stream, that should control the connection. For example:
>
> auto s = Socket("123.456.455.1");
> auto stream = s.byChunk(1024 * 16);
> ... stream is an input range of ubyte[] ...
> s.close();
>
> If the range defines a close() operation, then we need to start talking
> about it defining an open() operation, which complicates matters. Why
> not leave ranges for traversal and handles for connections?
>

Maybe, your Handle is similar to my Stream.
The open() operation can replace it by a constructor, but the close() 
operation is substitute impossibility by destructor.
Because, destructor may not be called when a struct data managed by GC.
The story is different if D offers a method to perform better RTTI.

> - On to output streams. What's wrong with having an output range of
> ubyte[]? Its put() primitive would be the same as the proposed write()
> routine.
>

I think it is good idea that Ranges for OutputStream. Now, 
LockingTextWriter just likes this.

> - flush() would be a good optional addition to an output stream.
>

Do you mean BufferedRange? It's interesting.

> - I have the same feeling about close() for output streams.
>

Me too.

> - The Seekable idea is good, I was thinking of it for a while. It
> expresses a range that is not as cheap for random access as a
> random-access range, but also that makes random seeking possible. What
> kind of algorithms could use Seekable?
>

I think that Seekable is unnecessary for Range.
Seekable should be had by Stream. In Container, slice is this.

> - What's the purpose of StreamWrapper? And why is it reading in the
> write() primitive?
>

For override.

interface X {
     InputStream getInputStream();
}
class Y: X {
     InputStream getInputStream(){ return 
wrap(FileStream("/path/to/file")); }
}
class Z: X {
     InputStream getInputStream(){ return wrap(SocketStream(socket)); }
}

Or, for arrays.

InputStream[] ins;
ins ~= wrap(FileStream("/path/to/file"));
ins ~= wrap(SocketStream(socket));

wrap is workaround for case that someone wants to employ interface by 
all means. If override of template function is possible, the story may 
be different.

And sorry, reading in the write() primitive is my miss.

> - ByLine is a bit awkward because it needs to read buffers of size 1.
> Clearly there is some problem there. The right way is to build
> ByLine!Char on top of a stream of Char, not a stream of Char[].
> (Speaking of which, I just checked in BlockingInputReader. It does read
> one character at a time but it has an inefficiency caused by the FILE*
> interface.)
>

I think so, too. Because it is only a mere demonstration, the 
implementation is slipshod.

> - What does FileStream do that File doesn't or can't do?
>

It is just an Adapter.

> Let me know of what you think.
>
>
> Andrei


More information about the phobos mailing list