deprecating std.stream, std.cstream, std.socketstream
H. S. Teoh
hsteoh at quickfur.ath.cx
Wed May 16 13:30:43 PDT 2012
On Wed, May 16, 2012 at 04:15:22PM -0400, Steven Schveighoffer wrote:
> On Wed, 16 May 2012 15:38:02 -0400, H. S. Teoh
> <hsteoh at quickfur.ath.cx> wrote:
[...]
> >One direction that _could_ be helpful, perhaps, is to extend the concept
> >of range to include, let's tentatively call it, a ChunkedRange.
> >Basically a ChunkedRange implements the usual InputRange operations
> >(empty, front, popfront) but adds the following new primitives:
> >
> >- bool hasAtLeast(R)(R range, int n) - true if underlying range has at
> > least n elements left;
> >
> >- E[] frontN(R)(R range, int n) - returns a slice containing the front n
> > elements from the range: this will buffer the next n elements from the
> > range if they aren't already; repeated calls will just return the
> > buffer;
> >
> >- void popN(R)(R range, int n) - discards the first n elements from the
> > buffer, thus causing the next call to frontN() to fetch more data if
> > necessary.
> >
>
> On such ranges, what would popFront and front do? I'm assuming since
> frontN and popN are referring to how many elements, and since the most
> logical definition for elements is bytes, that front gets the next
> byte, and popFront discards the next byte. This seems useless to me.
How so? It's still useful for implementing readByte, for example.
> I still don't get the need to "add" this to ranges. The streaming API
> works fine on its own.
>
> But there is an omission with your proposed API regardless --
> reading data is a mutating event. It destructively mutates the
> underlying data stream so that you cannot get the data again. This
> means you must double-buffer data in order to support frontN and
> popN that are not necessary with a simple read API.
>
> For example:
>
> auto buf = new ubyte[1000000];
> stream.read(buf);
>
> does not need to first buffer the data inside the stream and then
> copy it to buf, it can read it from the OS *directly* into buf.
[...]
The idea is that by asking for N elements at a time instead of calling
front/popFront N times, the underlying implementation can optimize the
request by creating a buffer of size N and have the OS read exactly N
bytes directly into that buffer.
// Reads 1,000,000 bytes into newly allocated buffer and returns
// buffer.
auto buf = stream.frontN(1_000_000);
// Since 1,000,000 bytes is already read into the buffer, this
// simply returns a slice of the same buffer:
auto buf2 = stream.frontN(1_000_000);
assert(buf is buf2);
// This consumes the buffer:
stream.popN(1_000_000);
// This will read another 1,000,000 bytes into a new buffer
auto buf3 = stream.frontN(1_000_000);
// This returns the same buffer as buf3 since we already have
// the data available.
auto buf4 = stream.frontN(1_000_000);
T
--
English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
More information about the Digitalmars-d
mailing list