Re: [buildcheapeeg] Managing a network of nodes and data streams in one thread

From: Dave (dfisher_at_pophost.com)
Date: 2002-03-27 16:45:31


On Thu, 21 Mar 2002 15:17:57 +0000, Jim Peters wrote:

Hey Jim--I have several questions concerning your "byte stream" replacement
data model.

>class Node {
> InPort in[];
> OutPort out[];
> void process() {};
>};
>
>class InPort {
> OutPort link;
> int cnt;
>};
>
>class OutPort {
> double val;
> int cnt;
>};

In OutPort, you have one single 'val' and a 'cnt'. What does 'cnt' refer to?
Since 'val' is not an array or pointer, I am not sure how 'cnt' is being used.
Is this just a sequence counter for the out[] array of sample values? But
below you mention that when you want to add a value, you stuff it in
out[nn].val and increment out[nn].cnt. What is 'nn' -- the next spot on the
stack to push a sample value? In that case, 'cnt' for that out[nn].val would
always be 1, since it is a new push. I dunno; I think I am not understanding
the implementation clearly.

Also, am I right in assuming that the Sensor class would inherit Node since
these are the classes interested in sending data? If that is the case, is it
necessary for every Node to have an InPort link, or can that be null to
indicate that there is no input link?

>It works like this: Every object that is interested in sending data
>out or receiving data in inherits from Node. This allows it to set up
>a list of its input and output ports. It, or some other code, can
>then connect the input ports to the output ports of other Nodes by
>setting the 'link' member of the InPort.

Can you give some concrete examples of what that input/output linkage would
look like using sensor data and/or dsp processing? Could you give one or more
real life case examples to help me ground my understanding?

>Node-supervisor code somewhere can keep a list of all Nodes and scan
>them to see which depend on which others through their InPort 'link'

Would the Node-supervisor be a part of BioDevice, in that it sits waiting for
data from the device, and then scans the node list to see who gets what?

>members. It can then sort them into an order that makes sure that
>nothing gets run before data is available for it. So long as we are
>not permitting feedback loops, this is easy.
>
>The procedure for outputting data goes like this:
>
>- Put a new value into out[nn].val
>- Increment out[nn].cnt
>
>That way anyone watching knows that a new value is available.

How does one watch for new values? Is this done by viture of the fact that
they have added themselves as a Node to the node list with their own process()
routine? Is this similar to the MVC pattern which registers several callback
views via an update() routine for a given resource? Is this watching triggered
by a wait state on select()? ??

>The Node-supervisor code can check to see if the OutPort 'cnt' value
>differs from the in[nn].cnt value for any InPort pointing to it
>through its in[nn].link. If it differs, then there is new data for
>that InPort, which means that the Node process() function should be
>called. The Node handling code can update the in[nn].cnt values to
>match the linked-to out[nn].cnt value (i.e. in[nn].link.cnt) after the
>Node process() call has returned.

So, in other words, at some point the Node-supervisor does a dependency check
for all output ports that have linked input ports to make sure that waiting
output data has actually been sent through the InPort link mechanism?

Also, just what does the process() method do? Is this a virtual method
dependent on just what the Node needs to do with the data (such as display it,
do some mathematical processing on it, such as FFT filtering, or somesuch)? Or
is process() a function that simply moves the floating piont value from
out[nn].val to in[nn].link.val and update the 'cnt's?

>Unlike Dave's system, this is only useful for interconnecting things
>within memory, and within the same thread. In that sense it is less
>flexible, but faster. It also assumes that data streams are split up
>into individual streams of floating point values.

I'll be better able to speak to this to see after I have a better grasp of your
proposal, and see if there is a way to use the process() method as a means to
transfer data in other ways, perhaps as a callback function to a socket or
somesuch. I like what you outline as it does have a lot less overhead than the
block-and-unblock method of threads and other sharing mechanisms.

>This is all just the basic level -- we could extend this to allow a
>Node to give short labels to its input and output ports so that they
>are easier to identify using names rather than numbers, which might
>allow the interconnections to be setup more easily from a config file.
>Also the Nodes themselves could be given short labels when they are
>created.
>
>I guess someone will want to write lots of wrapper functions with long
>names to encode what I just outlined. It seems really unnecessary to
>me, but if that's what makes people happy ...

Well, gotta tell you. Those names to encode what you outlined sure would help
this visually oriented person. We simply have different learning and
comprehension styles. Personally, I marvel at someone capable of purely
abstract and logical thought. I tend to think in pictures and descriptions,
and while abstract logic is part-and-parcel of our work, it is not "first
nature" for me. So I'll be the first to write a few wrapper functions... :)

Dave.



This archive was generated by hypermail 2.1.4 : 2002-07-27 12:28:43 BST