/******* ** ** To compile sequentially: pcc bounded.pc -o bounded.seq -lm ** Adapted for PARSEC 10-9-97 by Monnica Terwilliger ** *******/ /************************************************************************ ** ** Bounded Buffer Producer/Consumer Simulation ** ** This example simulates a system with one producer, one consumer, ** and one bounded buffer. ** ** The entity types used in this example are: ** ** producer: Produces MAX_ITEM of products ** consumer: Consumes MAX_ITEM of products ** buffer: Stores products generated by producer ** driver: Initiates the simulation ** ************************************************************************/ #include #define MAX_ITEM 300 /* Maximum number of items */ #define MAXSERVE 10 /* Maximum consuming time */ #define MAXPRODUCE 10 /* Maximum producing time */ #define Q_LENGTH 3 /* Buffer's size */ message product { ename producer; }; message req{ ename consumer;}; message token{ }; entity consumer (ename); entity producer (ename); entity buffer (); entity consumer(ename buffer) { int t, i; clocktype now; int t_used; message product new_product; unsigned short seed[3]; seed[0] = seed[1] = seed[2] = 2; now = t_used = 0; for(i=0; i < MAX_ITEM; i++) { send req { self } to buffer; /* Request for a product */ receive (product temp) { new_product = temp; } /* Stores product locally */ t_used += (t = pc_nrand(seed)%MAXSERVE); /* Statistic data collection */ hold (t); /* Consumes the product */ } now = simclock(); printf("Consumer utilization is\t%f\n",((float)(t_used)/(float)now)); } entity producer(ename buffer) { int i, n; clocktype now, t_wait, randnum; unsigned short seed[3]; seed[0] = seed[1] = seed[2] = 2; now = t_wait =0; n = Q_LENGTH; /* Number of tokens is Q_LENGTH */ for(i=0; i < MAX_ITEM; i++) { if(n==0) { /* If runs out of token wait */ now = simclock(); receive (token signal) /* Receives a token */ n++; t_wait += simclock()-now; /* Collects statistics */ } randnum = (clocktype) pc_nrand(seed)%MAXPRODUCE; hold (randnum); /* Produces one product */ n--; /* Decrement the token */ send product{self} to buffer; /* Deposits the product to buffer */ } now = simclock(); printf("Producer utilization is\t%f\n",((float)(now - t_wait)/(float)now)); } entity buffer() { ename producer; int q, tstart, tend, i, v; tstart = (int) simclock(); for(i=q=v=0;;) { receive (product dummy_product) when (q < Q_LENGTH) /* Accepts a product if not Full */ { tend = (int) simclock(); v += q*(tend-tstart); tstart = tend; q++; producer = dummy_product.producer; } or receive (req dummy_req) when (q > 0) { /* Gives a product if not empty */ send product {producer} to dummy_req.consumer; tend = (int) simclock(); v += q*(tend-tstart); tstart = tend; q--; if((++i) < MAX_ITEM) send token {} to producer; else break; } } printf("The average number of items in buffer: %f\n", (float)v/(float)simclock()); } entity driver() { ename b,p,c; b = new buffer(); new producer (b); new consumer (b); printf("\nBounded Buffer Producer/Consumer Simulation\n"); printf("\nSimulating Producint/Consuming %d items with buffer size: %d\n", MAX_ITEM, Q_LENGTH); }