home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mega CD-ROM 1
/
megacd_rom_1.zip
/
megacd_rom_1
/
MAGAZINE
/
DDJMAG
/
DDJCSPEC.ZIP
/
GEHANI.LST
< prev
next >
Wrap
File List
|
1989-11-21
|
11KB
|
438 lines
_DISCRETE EVENT SIMULATION IN CONCURRENT C_
by Narain Gehani and W.D. Roome
[LISTING ONE]
File: sim-sched.h
process spec sched() {
trans long now() /* return simulated time */
trans long reqDelay(long del);
/* request delay */
trans long wait(long x); /* wait for delay */
trans void addUser(); /* add client */
trans void dropUser(); /* drop client */
trans void passive(); /* client is passive */
trans void active(); /* client is active */
};
[LISTING TWO]
File: sim-source.h
process spec source(
process sched s, /* scheduler */
process queue outQ, /* output queue */
long meanIat, /* mean inter-arrival time */
long meanServt, /* mean service time */
long nGen, /* number to generate */
name_t name); /* symbolic name */
[LISTING THREE]
File: sim-server.h
process spec server (
process sched s, /* scheduler */
process queue inQ, /* input queue */
process queue outQ, /* output queue */
double speed, /* speed of server */
name_t name); /* symbolic name */
[LISTING FOUR]
File: sim-qItem.h
typedef struct {
/* Public: */
long servt; /* service time for job */
long arrive; /* time job arrived */
/* Private to queue process: */
long qEnter; /* time entered queue */
int ticket; /* ticket from takeReq */
int gotItem; /* !=0 if item was taken */
} qItem;
[LISTING FIVE]
File: sim-queue.h
process spec queue(
process sched s, /* scheduler */
int maxSize, /* max queue size */
name_t name) /* symbolic name */
{
trans int itemCnt(); /* return queue size */
trans void addProd(); /* add producer */
trans void dropProd(); /* drop producer */
trans void addCons(); /* add consumer */
trans void dropCons(); /* drop consumer */
/* start and finish put request:*/
trans int putReq(qItem);
trans void putWait(int, qItem);
/* start and finish take request:*/
trans qItem takeReq();
trans qItem takeWait(int);
};
[LISTING SIX]
File: sim-stats.h
typedef struct {
long nv; /* number of values */
long maxv; /* max value */
double sumv; /* sum of values */
double sumsq; /* sum of squares */
} stats;
void stInit(); /* initialize structure */
void stVal(); /* add new value */
double stMean(); /* return mean value */
double stSdev(); /* return standard deviation */
long erand(); /* exponential random number */
[LISTING SEVEN]
File: sim-main.cc
name_t makeName(name) char *name;
{ name_t ret;
strcpy(ret.str, name);
return ret;
}
main()
{ process sched s;
process queue q1, q2;
long nGen=100000; /* number of jobs */
long servt=500; /* mean service time */
long iat=1000; /* mean inter-arrival */
/* Create virtual time scheduler. */
s = create sched(); s.addUser();
/* Create queues and servers. */
q1 = create queue(s, 100, makeName("Q1"));
q2 = create queue(s, 100, makeName("Q2"));
create source(s, q1, iat, servt, nGen,
makeName("Src"));
create server(s, q1, q2, 0.5,
makename("Serv1.1"));
create server(s, q1, q2, 0.5,
makename("Serv1.2"));
create server(s, q2, c_nullpid, 1.0,
makename("Serv2"));
/* Wait for all processes to start. */
delay 2.0; s.dropUser();
}
[LISTING EIGHT]
File: si-source.cc
process body source(s, outQ, meanIat,
meanServt, nGen, name)
{ stats iat, servt;
qItem item;
long i, t;
/* Initialization phase */
s.addUser();
outQ.addProd();
stInit(&iat); stInit(&servt);
/* Main processing phase: generate jobs. */
for (i=1; i <= nGen; i++) {
t = erand(meanIat);
stVal(&iat, t);
item.arrive = s.wait(s.reqDelay(t));
item.servt = erand(meanServt);
stVal(&servt, item.servt);
qPut(outQ, item);
}
/* Termination phase: print stats, etc. */
print statistics;
outQ.dropProd(); s.dropUser();
}
[LISTING NINE]
File: sim-server.cc
process body server(s, inQ, outQ, speed, name)
{ stats sysTime; /* time-in-system */
qItem item;
long ts;
s.addUser(); stInit(&sysTime);
inQ.addCons();
if (outQ != c_nullpid)
outQ.addProd();
while (qTake(inQ, &item)) {
ts = s.wait(s.reqDelay(item.servt/speed));
stVal(&sysTime, ts - item.arrive);
if (outQ != c_nullpid)
qPut(outQ, item);
}
print statistics;
if (outQ != c_nullpid)
outQ.dropProd();
inQ.addCons(); s.dropUser();
}
[LISTING TEN]
File sim-qPut.cc
/* Put item onto queue; wait if full. */
void qPut(q, item)
process queue q; qItem item;
{ int ticket = q.putReq(item);
if (ticket >= 0)
q.putWait(ticket, item);
}
/* Set *itemp to next item; wait if empty. */
/* Return 1 if item was taken, 0 on EOF */
int qTake(q, itemp)
process queue q; qItem *itemp;
{
*itemp = q.takeReq();
if (itemp->ticket >= 0)
*itemp = q.takeWait(itemp->ticket);
return itemp->gotItem;
}
[LISTING ELEVEN]
File: sim-qInfo.h
/* *tInfo: Describe outstanding tickets. */
typedef struct {
int acc; /* next ticket to accept */
int give; /* next ticket to give out */
int nPass; /* pending passive clients */
} tInfo;
/* qInfo: Describe one queue. */
typedef struct {
process sched s; /* scheduler process */
int max; /* max queue size */
int nProd; /* number of producers */
int nCons; /* number of consumers */
name_t name; /* name of queue */
stats qTime; /* time-in-queue stats */
stats qSize; /* for queue size stats */
int nElem; /* items in queue */
int head; /* index head of queue */
int tail; /* index tail of queue */
qItem *items; /* alloc'd array of items */
/* Describe pending put, take requests: */
tInfo pPut, pTake;
} qInfo;
[LISTING TWELVE]
File: sim-queue.cc
process body queue(s, maxSize, name)
{ qInfo q; qItem x;
initialize qInfo structure;
accept addProd() { q.nProd++; }
while (q.nProd+q.nCons >0) {
select {
(q.nElem<q.max && q.pPut.acc==q.pPut.give):
accept putReq(item)
{ putItem(&q, &item); treturn -1; }
or (q.nElem==q.max):
accept putReq(item)
{ s.passive(); q.pPut.nPass++;
treturn incTick(&q.pPut.give); }
or (q.nElem<q.max):
accept putWait(qt, item)
suchthat (qt == q.pPut.acc)
{ putItem(&q, &item);
incTick(&q.pPut.acc); }
or (q.nElem>0 && q.pTake.acc==q.pTake.give):
accept takeReq()
{ treturn takeItem(&q); }
or (q.nElem==0):
accept takeReq()
{ x.ticket = incTick(&q.pTake.give);
s.passive(); q.pTake.nPass++;
treturn x; }
or (q.nElem>0):
accept takeWait(qt)
suchthat (qt == q.pTake.acc)
{ incTick (&q.pTake.acc);
treturn takeItem(&q); }
or (q.nProd==0 && q.nElem==0):
accept takeWait(qt)
{ x.gotItem = 0; treturn x; }
or accept itemCnt() { treturn q.nElem; }
or accept addCons() { q.nCons++; }
or accept addProd() { q.nProd++; }
or accept dropCons() { q.nCons--; }
or accept dropProd() { q.nProd--; }
}
/* On EOF, make pending takers active. */
if (q.nProd==0 && q.nElem==0)
for (; q.pTake.nPass > 0; q.pTake.nPass--)
s.active();
}
print statistics;
}
[LISTING THIRTEEN]
File: sim-qAux.cc
/* Increment ticket, return prev value. */
int incTick(tp)
int *tp;
{ int t = *tp;
*tp = (t+1)%10000;
return t;
}
/* Remove and eturn the next item in the queue. */
qItem takeItem(qp)
qInfo *qp;
{
qItem item;
item = qp->items[qp->head];
item.ticket = -1;
item.gotItem = 1;
stVal(&qp->qTime, qp->s.now() - item.qEnter);
qp->nElem--;
qp->head = (qp->head+1) % qp->max;
if (qp-pPut.nPass >0)
{ qp->s.active(); qp->pPut.nPass--; }
return item;
}
/* Add item *itemp to queue. */
void putItem(qp, itemp)
qInfo *qp; qItem *itemp;
{
qp->items[qp->tail] = *itemp;
qp->items[qp->tail].qEnter = qp->s.now();
stVal(&qp->qSize, qp->nElem);
qp->nElem++;
qp->tail = (qp->tail+1) % qp->max;
if (qp->pTake.nPass > 0)
{ qp-<>s.active(); qp->pTake.nPass--; }
}
[LISTING FOURTEEN]
File: sim-sched.cc
process body sched()
{ int nUser, nAct, i;
long curTime = 0; /* Current simulated time */
ordered list of pending delay requests;
initialize pending delay list data structures;
accept addUser() { nUser = nAct = 1; }
while (nUser >0) {
select {
accept addUser() { ++nUser; ++nAct; }
or accept dropUser() { --nUser; --nAct; }
or accept active() { ++nAct; }
or accept passive() { --nAct; }
or accept now() { treturn curTime; }
or accept reqDelay(x)
{ add request for curTime+x to pending delay list;
nAct--; treturn request-index; }
}
if (nAct == 0 && pending delay list is not empty) {
curTime = time of request at head of list;
nAct = number of processes waiting for that time;
for (i = 1; i <= nAct; i++)
accept wait(x)
suchthat (x == index-of-head-request)
{ treturn curTime; }
discard request at head of pending delay list;
}
}
}
Example 1: The Server Process
while (1) {
delay for random inter-arrival time;
generate item;
call queue process to put item in queue;
}
Example 2: Moving Jobs Between Queues
qItem item;
process queue qFrom, qTo;
while (qTake(qFrom, &item))
qput(qTo, item);
Example 3: Generating Random Numbers
stats mystats;
int i;
stInit(&mystats);
for (i = 1; i <= 10000; i++)
stVal(&mystats, erand(100));
printf("Mean is %lf\n", stMean(&mystats));
Example 4: Choosing Queues
if (outQ1.itemCnt() < outQ2.itemCnt())
qPut(outQ1, item);
else
qPut(outQ2, item);
Example 5: An Example of main()
main()
{
create all processes
while (1) {
s.wait(s.reqDelay(10000));
for each entity process p
entity-stats = p.giveStats();
if (statistics have been stable for long enough)
break;
}
print final statistics
for all processes p
c_abort(p);
}