Stream comments

git-svn-id: svn://ultimatepp.org/upp/trunk@2604 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2010-08-13 08:27:23 +00:00
parent 961549b592
commit b82b4f3e6d

View file

@ -0,0 +1,135 @@
topic "About Stream";
[2 $$0,0#00000000000000000000000000000000:Default]
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
[l288;2 $$2,2#27521748481378242620020725143825:desc]
[0 $$3,0#96390100711032703541132217272105:end]
[H6;0 $$4,0#05600065144404261032431302351956:begin]
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:item]
[l288;a4;*@5;1 $$6,6#70004532496200323422659154056402:requirement]
[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param]
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
[b42;2 $$9,9#13035079074754324216151401829390:normal]
[{_}
[s0; [*R6 About Stream]&]
[s0; [/ (some loosely organized comments about Stream by Konstantin
Hartwich)]&]
[s0;/ &]
[s0;i150;O0; Stream represents only a logical `'cut out piece`' or
a finite snapshot of a per definition concurrent, infinite data
stream, beeing processed, handled or available to some extent.
hence the pos variable, indicating the current offset or pos`'ition
of the data chunk represented by your Stream instance, from the
logical start or beginning of stream.&]
[s0; &]
[s0;i150;O0; Stream is basicly only an interface class with some
pointers to ref some memory somewhere. it usually does not contain
the data itself. Thats why it may have MemStream, StringStream,
FileStream etc.. `'they`' access or even contain (StringBuffer)
the buffer and are using the pointers from Stream base to handle
it. The buffer is a current chunk of data, `*entirely`* accessable
in your stream.&]
[s0; &]
[s0;i150;O0; Stream is unidirectional per definition and should be
used as such. In Contrast to other Stream implementations, Upp
Stream brings in all to be used both as Input or as Output stream.
these 2 modes are supported in one single instance, but should`'t
be used at same time. Mevertheless, it does not produce ASSERT,
Exception or sth. if one tries to Put and Get stuff from same
Stream, it simply might not be logical or what you expect, because
Stream uses only one ptr to represent current `'head`' position
for reading or writing. (thus it is not intrinsically possible
to use a MemStream as a Circular Buffer, which would be nice.
btw, how about implementing such one Rolling Eyes . These 2 Modes
can be differed using the API functions IsStoring() / IsLoading().
The Modes are set using SetStoring() / SetLoading() and are normally
set automatically, depending on how you created the stream instance.&]
[s0; &]
[s0;i150;O0; in both modes, the extension of the buffer marks the
accessible space for reading or writing. for reading, it means
the current available, `*already read`* data chunk, from buffer
to rdlim. ptr meaning the read position currently processing
it. the space from ptr till rdlim meaning the still to read data.
For writing, it means the `*already allocated`* data for beeing
able to write to. buffer to wrlimit is its extension. buffer
till ptr meaning the data, already written to the space, ptr
till wrlim the space free to fill.&]
[s0; &]
[s0;i150;O0; Serializing stuff to Stream is quite cool. in other
implementations, Stream has a split interface for serializing
and deserializing stuff, so the user had to keep track which
order the elements go and use 2 different functions basicly,
for Serializing and Deserializing. upp stream puts away this
head ache. it uses 1 interface, and handles the difference about
serialize/deserialize internally `& implicitly with the help
of IsLoading() / IsStoring()..the user benefits from this only
having to specify `*one`* functionional place, that determines
the order of serialization and that is maintained the same on
both directions, hurray. (drawback, one cant deserialize from
a `'const Stream `&`', because the function needs a `'Stream
`&`', but the case where this happens is to be neglacted). since
this is somehow unusual, one needs to get familiar with the Stream.&]
[s0; &]
[s0;i150;O0; A global template operator%(Stream `&, T `&) enables
your class to be serialized as well by the user, simply calling
stream % yourclass. to make this happen, provide a `'void Serialize(Stream`&
s)`' function in your class, where you define the the behaviour
and order of de/serialization of your content (other data types
also beeing serializable). after deserializing your class, finishing
init of your class should be done. this makes handling of data
transport using Socket quite easy, but is not yet implemented
Smile&]
[s0; &]
[s0;i150;O0; You can easily implement own buffered Streams, it provides
a mainly protected interface. Stream provides a rich default
serialization interface to serialize all kind of stuff, including
NTL containers...(recursively calling serialize on them then
as well..)&]
[s0; &]
[s0;i150;O0; One should know pretty well what kind of Stream to use
what for.. i.e. a MemStream cant be used as a self growing Buffer,
it handles only a previously provided chunk of memory which cant
grow just like that (because the memory chunk cant grow). for
this purpose, use StringStream.&]
[s0; &]
[s0;i150;O0; The basic [/ implementation] of a Stream is this: a Stream
refers to a chunk of memory, represented by `'buffer`' pointer.
it implicitly stores its size with the rdlim and wrlim pointers,
representing the extension of the buffer for reading and writing
operations. every API function asumes that it can store or read
its data directly in this chunk of data, at ptr location, normally
whitout invoking any kind of flush or the like, advancing the
ptr though. But sooner or later it will have consumed it`'s space
(reacing respective rdlim, means having read all, or wrlim, meaning
having written all). then it will claim some `'upper level`'
action to either provide more data, done by advanceing the snapshot
position in the read case, or writing out stored data and mark
it as free again. this is done invoking `_Get(..) or `_Put(..).
in other words... `_Put normally takes care of processing the
full buffer by flushing it somehow, and rewinding the ptr and
adjusting wrlim, declaring buffer empty. `_Get typically claims
some more data to be made available inside the Stream, maybe
by copying some data in buffer and again rewinding the ptr and
adjusting rdlim. this behaviour is to be defined somehow, and
is special for any kind of stream.&]
[s0; &]
[s0;i150;O0; Flushing behavior is not invoked by generic Stream implementation
by default. but higher level Streams use it in to do exacely
this. either providing more data or flushing it to the underying
destination.&]
[s0; &]
[s0;i150;O0; there are several helper functions around handling Streams,
even copying, which is normally not possible just like that,
or stuff like providing a version for streamed data and some
constraints on version (min, max) when serializing. take a look
in Stream.cpp.&]
[s0; &]
[s0;i150;O0; OutStream uses a small internal buffer to accumulate
things, before it forwards them to a to be user implemented Out(..)
function, which should take care of processing it somehow (sending
somewhere or what ever..)&]
[s0; &]
[s0;i150;O0; TeeStream is an OutStream that uses internal buffer
again, and when time has come, pushes it to 2 other streams..(so
a little `'data latency`' is expected..if you want to make the
data be available at once, call Flush() after your operations..&]
[s0; ]