Multiple Inputs

Top  Previous  Next

One thing we have not yet seen how to do is to wait for a message from any one of a number of concurrently executing tasks. For example, a multiplexor task that accepted messages on any of an arbitrary number of input ports and passed them on through a single output port would be a useful building block.

 

 

A task connected to the output port of the MUX task sees a sequential stream of messages, even though they are coming from any number of input tasks, in any order. The problem in implementing MUX is that we cannot simply issue channel read requests on the input channels in order. This is because a channel read does not terminate until the data have actually arrived and have been read. If the channel we pick has no message waiting to be read, the MUX task waits. In the meantime, all the other channels will be held up even if they have data to provide. What we need is a way to identify which channel has an incoming message waiting to be read. We can then issue a read on that channel alone.

 

The alt.h functions provide this facility.

 

Dragons003The ALT functions can be used only on internal or virtual channels; they do not work currently with physical channels.

 

Here, we give the flavour of these functions by showing a Diamond implementation of the multiplexor task that uses the alt_wait_vec function to wait for a message to arrive from any element of an array of (pointers to) channels. The multiplexor task's input port vector is just such an array of pointers to channels, so it can be passed directly to alt_wait_vec along with a count of the number of elements in the array.

 

alt_wait_vec waits for a message to become available on any of the channels pointed to by the array, in this case any of the multiplexor task's input ports. It then returns the index in the array of the channel that is ready to read a message. If more than one channel becomes ready at the same time, the system chooses which one to handle first. If no channel ever becomes ready, the function will never return.

 

Once alt_wait_vec has determined the channel on which a message is incoming, the rest of the MUX task is quite straightforward. First, read the message from that channel into a buffer, then echo the message to the single output port. In the example, the messages consist of a fixed length (one word) header giving the size of a trailing variable-length part. Only one message buffer is required no matter how many input ports are connected to the multiplexor task. Messages arriving on any other channels are blocked while the multiplexor deals with the current message.

 

// Examples\General\altmux.c

// message multiplexor using 'alt' package

#include <alt.h>

#include <chan.h>

main(int argc, char *argv[], char *envp[],

     CHAN *in_ports[], int ins,

     CHAN *out_ports[], int outs) {

   int msglen; // number of words in message

   char buf[1024]; // message buffer

   for (;;) { // read messages forever

      //

      // wait for a message on any input port

      //

      int i = alt_wait_vec(ins, in_ports);

      //

      // read the message from that port

      //

      chan_in_word(&msglen, in_ports[i]);

      chan_in_message(msglen, &buf[0], in_ports[i]);

      //

      // ...and copy it to the single output port

      //

      chan_out_word(msglen, out_ports[0]);

      chan_out_message(msglen, &buf[0], out_ports[0]);

   }

}