// sieve.cc // sample of how threads and bounded buffers (that use synchronization // primitives) can be used to do something quasi-useful, namely sieving // for primes. Note that no attempt is made to delete any dynamically // allocated objects, since they get cleaned up soon enough when the // program ends. -Max Hailperin 9/23/96 #include "system.h" #include "boundedbuf.h" class BBufPair{ // used just to pass two bounded buffers (input and output public: // channels) into a sieve thread packaged together BBufPair(BBuf *inBuf, BBuf *outBuf){in = inBuf; out = outBuf;} BBuf *in, *out; }; //---------------------------------------------------------------------- // Sieve // This procedure receives an int which should be cast back into a pointer // to a BBufPair, which in turn contains the sieves input and output // bounded buffers. The first number on the input is prime, and // none of the remaining numbers are divisible by any prime less than that // initial prime. The sieve is to copy all input numbers that are prime // to the output bounded buffer. //---------------------------------------------------------------------- void Sieve(int bufPairAddr){ BBufPair *p = (BBufPair*) bufPairAddr; BBuf *in = p->in; BBuf *out = p->out; int divisor; if(!in->get(divisor)){ out->shutdown(); // no input, so no output return; } out->put(divisor); // we were told this is prime BBuf *intermediate = new BBuf; Thread *sieve = new Thread("lower-level sieve"); sieve->Fork(Sieve, (int) new BBufPair(intermediate, out)); int n; while(in->get(n)){ if(n % divisor != 0){ // if we can't already prove it composite intermediate->put(n);// give the next sieve a chance } } intermediate->shutdown();// no more in, so no more out to next sieve } //---------------------------------------------------------------------- // Printer // This gets as its integer argument a value that it should cast // to be a pointer to a bounded buffer, which is the printer thread's // input source. Each prime read from that bounded buffer gets printed // out, and a message when there are no more //---------------------------------------------------------------------- void Printer(int bufAddr){ BBuf *in = (BBuf*)bufAddr; int prime, count=0; while(in->get(prime)){ printf("prime %d is %d\n", ++count, prime); } printf("end of primes\n"); } //---------------------------------------------------------------------- // ThreadTest // This is the main startup procedure, called from main. It // sets up the bounded buffer communication channels and the sieving // and printing threads, and then itself becomes the enumerating thread // that feeds the whole pipeline. //---------------------------------------------------------------------- void ThreadTest() { BBuf *enumToSieve, *sieveToPrinter; Thread *sieveThread, *printerThread; DEBUG('t', "Entering SieveTest"); enumToSieve = new BBuf; sieveToPrinter = new BBuf; sieveThread = new Thread("top-level sieve thread"); printerThread = new Thread("printer thread"); sieveThread->Fork(Sieve, (int) new BBufPair(enumToSieve, sieveToPrinter)); printerThread->Fork(Printer, (int) sieveToPrinter); for(int i = 2; i <= 1000; i++){ enumToSieve->put(i); } enumToSieve->shutdown(); }