/******* ** ** To compile: mc bounded.m -o bounded -lm ** *******/ /************************************************************************ ** ** 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 "maisie.h" /* Include Maisie system file */ #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 */ entity consumer{buffer} ename buffer; { int t, i; int now, t_used; message product {} new_product; now = t_used = 0; for(i=0; i < MAX_ITEM; i++) { invoke buffer with req { self }; /* Request for a product */ wait until mtype(product) new_product = msg.product; /* Stores product locally */ t_used += (t = random()%MAXSERVE); /* Statistic data collection */ wait t until mtype(timeout); /* Consumes the product */ } now = cti(sclock()); printf("Consumer utilization is\t%f\n",((float)(t_used)/(float)now)); } entity producer{buffer} ename buffer; { int i, n; int now, t_wait; message token{} dummy_token; 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=cti(sclock()); wait until mtype(token)/* Receives a token */ n++; t_wait += cti(sclock())-now; /* Collects statistics */ } wait (random()%MAXPRODUCE) /* Produces one product */ until mtype(timeout) n--; /* Decrement the token */ invoke buffer with product{self}; /* Deposits the product to buffer */ } now = cti(sclock()); printf("Producer utilization is\t%f\n",((float)(now - t_wait)/(float)now)); } entity buffer{} { message product { ename producer; } dummy_product; message req{ ename consumer;} dummy_req; ename producer; int q, tstart, tend, i, v; tstart = cti(sclock()); for(i=q=v=0;;) { wait until { mtype(product) st(q < Q_LENGTH) { /* Accepts a product if not Full */ tend = cti(sclock()); v += q*(tend-tstart); tstart = tend; q++; producer = msg.product.producer; } or mtype(req) st(q > 0) { /* Gives a product if not empty */ invoke msg.req.consumer with product; tend = cti(sclock()); v += q*(tend-tstart); tstart = tend; q--; if((++i) < MAX_ITEM) invoke producer with token; else break; } } } printf("The average number of items in buffer: %f\n", (float)v/ctf(sclock())); } 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); }