[Coldstuff] $stream
xmath
xmath@nubz.org
Sat, 12 Jan 2002 01:46:39 +0100
I've been requested to give some details on the architecture of
$stream and descendents. First of all, I'm still fiddling with them,
but they can be viewed by going to:
http://ice.cold.org:1180/bin/object?target=stream
and following the links from there
I also had $local_stream and $local_listener, but I wasn't happy with
'em yet so I destroyed them. I'll see if I can make 'em again
tomorrow.
Why $stream?
I basically created it because of a few separate issues I had with
networking, in genesis and coldcore (UDP is poorly implemented, the
negative port-number for udp using open_connection is a kludge, and
in generic there's no room for other protocol, $connection is
line-oriented without byte-oriented equivalent etc). I designed
$stream to be a generic and clean system for IO.
What is a $stream?
Basically anything related to IO. The name "stream" doesn't imply
it's just byte-oriented. It equally well supports streams of
structures messages. Even the $tcp_listener is a $stream (you could
say a stream of incoming connections).
Architecture
The internal methods are prefixed with stream_ and are protected.
They're usually native methods. One major exception is stream_event
which is actually called by the IO-implementation (usually in
Genesis) to notify the stream-object of events.
All streams implement some form of stream_open and stream_close
(arguments may vary). Most streams also implement stream_read and
stream_write.
Internals
I'd replace both the conn and file fields of Obj by a single stream
field, a pointer to a structure with a file descriptor and some
flags. Buffering is done in ColdC rather than Genesis (I doubt this
will be significantly slower, especially since in Genesis,
buffer_append is used too). Native methods are placed on whichever
object is the best place to put them. For example, stream_close is
placed on $stream because it applies to all streams. If the stream is
actually fully implemented in ColdC (like local streams or wrapper
streams) then no harm is done.. they'll just override it
($stream.stream_close would do nothing or throw an error)
Object overview
$stream: any kind of stream
$data_stream: stream of bytes
$packet_stream: stream of discrete pieces of data (represented by
single values)
$listener_stream: the name says it all
$tcp_stream, $udp_stream, $tcp_listener, $file_stream should be obvious
$line_stream: a special mix-in to make a stream of bytes into a stream of lines
In all cases, .stream_read and .stream_write are non-buffered and
non-blocking. The high-level method .read and .write are buffered and
blocking by default, but this can be overridden with flags.
In case of $tcp_stream, stream_close is not immediate, but instead
will cause a close-event when the close has been acknowledged. You
can make it immediate by specifying the 'immediate flag.
The $line_stream object is easy to use: for example, to make a
line-based TCP stream, make an object with parents: $line_stream,
$tcp_stream (in that order) and it works.
Note that streams are passive: you just get notified when data has
arrived, you still have to read it yourself. You could for example
put a loop in .read_notify that reads lines (non-blocking) and calls
.parse_line, until no more lines are available.
Well, looks like this is about it. I'm gonna sleep, bye :-)
- xmath