Chapter 13. WvStreamList - dealing with multiple streams

Table of Contents
Don't do this
Do this instead
An Interesting Example

WvStreamList is one of the most important parts of the WvStreams library. Almost every real WvStreams program (in contrast with all the preceding examples) involves at least one WvStreamList. We would have mentioned it much sooner, but we thought it would be nice to have a few different kinds of streams to play with before we started creating lots of them at a time.

Fundamentally, what WvStreamList does is allow you to select() on more than one stream at a time. That way you can, for example, wait for multiple TCP connections to send you data, and wake up immediately as soon as any one of them is available. Without the magic of WvStreamList, there is no good way to wait for multiple streams simultaneously. There are, however, a couple of bad ways, which we will mention shortly just so you don't try them.

Don't do this

Don't try this:

	  
/*
 * A WvPipe example.
 *
 * Some text about this example...
 */

#include <wvpipe.h>

int X = -1;
// int X = 0;
// int X = 1000;

int main()
{
    const char *argv1[] = { "sh", "-c", "while :; do echo foo; sleep 3; done", NULL };
    const char *argv2[] = { "sh", "-c", "while :; do echo snorkle; sleep 1; done", NULL };

    WvPipe stream1(argv1[0], argv1, false, true, false);
    WvPipe stream2(argv2[0], argv2, false, true, false);
    stream1.autoforward(*wvcon);
    stream2.autoforward(*wvcon);
    
    while (stream1.isok() || stream2.isok())
    {
	if (stream1.select(X))
	    stream1.callback();
	if (stream2.select(X))
	    stream2.callback();
    }
}

 	 

It will fail in three different ways depending on the value of X.

If X==-1, each select() statement waits forever for data. That means in order to print a snorkle (which should appear once per second), you must first print a foo (which only happens once every three seconds). That's bad enough, but some streams might be almost completely idle, so you certainly can't get away with doing that.

If X==0, we never wait at all. This will appear to work properly -- if you run the program, the snorkles and foos will show up at the right time. But unfortunately, your program will spin in the main loop, and take 100% of the CPU unnecessarily.

We can compromise by making X==1000 instead. That way, each select() statement will give up after 1 second. Since the snorkles only happen once per second, that should be okay. However, it's not perfect -- the snorkles should appear _exactly_ one second apart, but you can't guarantee that using this technique. It'll be somewhere between zero and one seconds, depending on random luck. Besides, the whole point of this chapter is there's a better way, so don't write programs like the one above.