#include #include #include /* A toy program to demonstrate working with * a main control thread, sending and receiving data * from N worker threads. The main thread can * send a character to a worker as well as receive from it. * Workers keep the characters they receive in a buffer. * so for example if we send each character of the string * 'TEST!12345' to 5 workers (round-robin) the first will keep * T1 in their stack, the second E2 etc. reading it back from the main * thread using the last worker that we sent first would reverse the * string to 54321!TSET. */ enum { CHARSTACK=512, STACK = 2048, }; /* one channel for data coming in, one for going out * worker threads should RCV on 0 and SND on 1 * master thread should SND on 1 and RCV on 0 */ void mkchanpair(Channel *cp[2]) { cp[0] = chancreate(sizeof(char), 0); cp[1] = chancreate(sizeof(char), 0); } void runthread(void *arg) { Channel **ic; char stack[CHARSTACK]; int ind; /* our index in the char stack */ ind = 0; ic = arg; char charrcv, charsnd; Alt a[] = { {nil, &charrcv, CHANRCV}, /* thread can receive a char */ {nil, &charsnd, CHANSND}, /* thread can send a char */ {nil, nil, CHANEND}, }; a[0].c = ic[0]; /* we are using a single chan for SND and RCV so set it */ a[1].c = ic[1]; /* thread name prints its id along with the send and rcv channel pointers */ threadsetname("[thread: %d/(r@%p)/(s@%p)]", threadid(), ic[0], ic[1]); print("%s started!\n", threadgetname()); for(;;){ switch(alt(a)){ case 0: stack[ind]=charrcv; charsnd=charrcv; print("%s received char: %c\n", threadgetname(), stack[ind]); ind+=1; /* increase our pointer in the char stack */ break; case 1: if(ind>0){ print("%s sending char: %c\n", threadgetname(), charsnd); ind-=1; /* if you try to ask an empty stack to send something * you will get a '?' character. */ charsnd=(ind>0)?stack[ind-1]:'?'; stack[ind]=0; } break; default: sysfatal("can't happen"); } } threadexits(0); } #define NSTACKS 5 void threadmain(int argc, char *argv[]) { char c; /* the main thread only has deals with 1 char at a time */ int i; Channel *chanps[NSTACKS][2]; char *test="TEST!"; /* the string to be sent one char each to the stacks */ char testchar; for(i=0; i=0; i--) recv(chanps[i%NSTACKS][1], &testchar); yield(); for(i=0; i