[ catching up on this; I deferred it cuz it was, um, *long* :-) ] On Wed, Aug 28, 2002 at 06:26:16PM -0700, Aaron Bannert wrote: >... > 1) Let's get away from the notion of Push and Pull, and go to the idea > where the app drives the filter chain, and each filter is given > control of a piece of data for a short period of time.
It appears that the model you describe below is a "full push" model. No pull whatseover. That's fine with me, as I think it is the best way for an app to be built. Hmm. The general notion of a push model, including yours, can still be used in a pull-mode if the app wants to do that. For example, the app can direct the socket SOURCE to push some data into the graph. The SINK simply holds onto the data and returns. The app then picks up the data. >... > 4) All graphs have by default two filters, a SOURCE and a SINK. The SOURCE > filter produces a single TRANSACTION (for lack of a better term), > and a SINK consumes the same. I was about to add to some of the notes my thought that a completely push model actually produces a "ring". You have a node that is the socket send/recv, and it loops the input through the "input filters" and back through the "output filters" to the socket again. Drawing it out, it produces a ring. The "application" would be just another node in the filter chain/ring. You've formalized my description of the ring a bit better. >... > 6) The application then uses the filter graph. If there are any unused inputs > or outputs, there is an immediate runtime error. The reason this is deferred > until the filter graph is actually used is so that the contents of the > graph can be modified at any time. (One can imagine wanting to add or > remove certain filters after a particular filter graph has been used, so > why limit ourselves here?) We'd want to look at the performance of graph setup/teardown. If it is expensive, then you'd want to be able to define/resolve a graph, and then reuse it over and over (which means that you want to isolate the definition of a graph from its runtime data; e.g. the filters inserted do not carry a *ctx field themselves (you could insert each filter with a data index, and they recover their ctx from an array of ctx pointers, where the array is per-transaction)). >... > Let's take a really simple example: Serving a static file via HTTP req/resp: > > - The types of filters I could imagine being involved here would be: I would nitpick these :-), but let's defer that conversation. Generally, your descriptions assumed too much info (how would the SOCKET_WRITER know where the endof a TRANSACTION lies?), and an attempt at balance (your diagram of "resolution") where one doesn't really exist. Basically, the SINK doesn't know anything about transactions. It is a bytestream. For that matter, same on the SOCKET_READER side: it just reads bytes and passes them along; it is the following filters which define the concepts and, thus, define the transactions boundaries. >... > Type System: > > So now we're going to have an explosion of new data types, how do we > manage this? My OOP training would love to be able to use a whole > inheritance system to deal with this, and although we don't have that > explicitly in the C language, I think that's what we're going to end > up having. Imagine something like this: I believe it will be flat, discrete types. But only belief... I'm not tussed about either direction. Cheers, -g -- Greg Stein, http://www.lyra.org/
