v14i069: SILO: An event-based simulation platform

S Manoharan sam at lfcs.ed.ac.uk
Thu Aug 30 08:48:05 AEST 1990


Posting-number: Volume 14, Issue 69
Submitted-by: sam at lfcs.ed.ac.uk (S Manoharan)
Archive-name: silo/part01

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	Bin.h
#	Counter.h
#	Debug.h
#	Entity.h
#	Event.h
#	Resource.h
#	Sim.h
#	SimEntityList.h
#	SimEventList.h
#	Bin.c
#	Debug.c
#	Entity.c
#	Event.c
#	Resource.c
#	Sim.c
#	SimEntityList.c
#	SimEventList.c
#	Test.c
# This archive created: Tue Aug 21 20:17:38 1990
# sam at lfcs.edinburgh.ac.uk


export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X/* $Author: sam $ $Date: 90/07/20 11:15:00 $ $Revision: 1.1 $ */
X
X      SILO	: An event-based simulation platform.
X			   ----
X	 S. Manoharan  sam at lfcs.edinburgh.ac.uk
X
X
XSILO is a library of C++ classes that provides building blocks
Xfor constructing event-based discrete event simulations. It 
Xprovides four basic classes: Entity, Event, Resource and Bin.
X
XRefer to
X at book{MacDo87,
X   author =	"M H MacDougall",
X   year =	"1987",
X   publisher =	"MIT Press",
X   title =	"Simulating Computer Systems: Techniques and Tools"
X}
Xfor a discussion on event-based simulations and a C implementaion.
XSILO closely follows the description of [MacDo87].
X
XClass Bin is a FIFO buffer of size infinity. Method `give' adds to
Xthe buffer; `take' removes from the buffer. `take' blocks when the
Xbuffer is empty.
X
XEvent *cause ( void );
X   returns the event with the earliest time from the event list.
Xshort cancel ( const int eid );
X   cancels the event with the event id eid; returns 1 if success;
Xdouble simtime ( void );
X   returns the current simulation time;
X
XNotes:
X-----
X1. Use g++ version 1.37.1 or greater. The g++ class library provides
Xclasses to generate random numbers.
X
X2. SILO is tested under g++ 1.37.1. Test.c provides an example 
Xexplained in [MacDo87].
X
SHAR_EOF
fi
if test -f 'Bin.h'
then
	echo shar: "will not over-write existing file 'Bin.h'"
else
sed 's/^X//' << \SHAR_EOF > 'Bin.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:17 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef Bin_H
X#define Bin_H
X
X#include "Entity.h"
X#include "SimEntityList.h"
X
Xclass Bin {
Xprivate:
X   char *bin_name;
X   int available;
X   short bin_used;
X   SimEntityList blockedQ;
Xpublic:
X   Bin(const int = 0, char *const s = 0);
X   virtual ~Bin()	{ }
X
X   virtual void set(const int sz);
X   virtual short status()	{ return available == 0; }
X
X   virtual short take(Entity *const bywho, const int event_type);
X   virtual void give();
X};
X
Xinline
XBin::Bin(const int sz, char *const s)
X{
X   available = sz;
X   bin_name = s;
X   bin_used = 0;
X}
X
X#endif Bin_H
SHAR_EOF
fi
if test -f 'Counter.h'
then
	echo shar: "will not over-write existing file 'Counter.h'"
else
sed 's/^X//' << \SHAR_EOF > 'Counter.h'
X/* $Author: sam $ $Date: 90/07/11 13:31:58 $ $Revision: 1.1 $ */
X
X#ifndef Counter_H
X#define Counter_H
X
Xclass Counter {
Xprivate:
X   double current;
X   double cycle;
Xpublic:
X   Counter(double init = 0, double tck = 1);
X
X   void set(const double t)		{ current = t; }
X   void tick(const double t)		{ cycle = t; }
X
X   double operator () () const		{ return current; }
X   void operator += (const double inc)	{ current += inc; }
X   void operator -= (const double dec)	{ current -= dec; }
X   void operator -- ()			{ current -= cycle; }
X   void operator ++ ()			{ current += cycle; }
X
X   double tick() const			{ return cycle; }
X};
X
Xinline
XCounter::Counter(double init, double tck)
X{
X   current = init, cycle = tck;
X}
X
X#endif Counter_H
X
SHAR_EOF
fi
if test -f 'Debug.h'
then
	echo shar: "will not over-write existing file 'Debug.h'"
else
sed 's/^X//' << \SHAR_EOF > 'Debug.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:21 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef Debug_H
X#define Debug_H
X
X#include <std.h>
X#include <stream.h>
X
Xextern int debug_flag; /* global debug flag */
X
Xinline int
Xdebug_level(const int level)
X{
X   return ( ::debug_flag > 0 && ::debug_flag <= level );
X}
X
Xextern void freeStoreException();
X
X#endif Debug_H
SHAR_EOF
fi
if test -f 'Entity.h'
then
	echo shar: "will not over-write existing file 'Entity.h'"
else
sed 's/^X//' << \SHAR_EOF > 'Entity.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:23 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef Entity_H
X#define Entity_H
X
Xclass Event; class Entity;
X
Xclass Entity {
Xfriend class Resource;
Xprivate:
X   int entity_id;
X   int prio;
X   char *entity_name;
X   int current_event;
X   double afterTime;
Xprotected:
Xpublic:
X   Entity(char *const s = 0);
X   virtual ~Entity()			{ }
X
X   int id() const			{ return entity_id; }
X   virtual void name(char *const s)	{ entity_name = s; }
X   virtual char *name() const		{ return entity_name; }
X
X   virtual void currentEvent(const int e)	{ current_event = e; }
X   virtual int currentEvent() const	{ return current_event; }
X   virtual void priority(const int p)	{ prio = p; }
X   virtual int priority() const		{ return prio; }
X
X   virtual void schedule(const double delay, Event *const ev);
X};
X
X#endif  Entity_H
SHAR_EOF
fi
if test -f 'Event.h'
then
	echo shar: "will not over-write existing file 'Event.h'"
else
sed 's/^X//' << \SHAR_EOF > 'Event.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:26 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef Event_H
X#define Event_H
X
Xclass Event; class Entity;
X
Xclass Event {
Xprivate:
X   int event_id;
X   int event_type;
X   double etime;
X   Entity *bywho;
Xprotected:
Xpublic:
X   Event(const int ev_type = 0);
X   virtual ~Event()	{ }
X
X   virtual int id() const			{ return event_id; }
X   virtual void type(const int n)		{ event_type = n; }
X   virtual int type() const			{ return event_type; }
X   virtual void eventTime(const double t)	{ etime = t; }
X   virtual double eventTime() const		{ return etime; }
X   virtual void scheduled_by(Entity *const who)	{ bywho = who; }
X   virtual Entity *scheduled_by() const		{ return bywho; }
X};
X
X#endif  Event_H
SHAR_EOF
fi
if test -f 'Resource.h'
then
	echo shar: "will not over-write existing file 'Resource.h'"
else
sed 's/^X//' << \SHAR_EOF > 'Resource.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:29 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef Resource_H
X#define Resource_H
X
X//
X// An entity can reserve a resource for an event of type event_type.
X// Reserved or preempted resources can later be released. Reserve,
X// if unsuccessful, places the entity in blockedQ and returns 0.
X// A release examines the blockedQ for blocked entities, removes
X// the head of the Q and re-schedules the event during which the entity
X// got blocked.
X//
X
X#include "Entity.h"
X#include "SimEntityList.h"
X
Xclass Resource {
Xprivate:
X   char *resource_name;
X   int available;
X   short resource_used;
X   SimEntityList blockedQ, servedQ;
Xpublic:
X   Resource(const int = 1, char *const s = 0);
X   virtual ~Resource()	{ }
X
X   virtual void set(const int sz);
X   virtual short status()	{ return available == 0; }
X
X   virtual short reserve(Entity *const bywho, const int event_type);
X   virtual short preempt(Entity *const bywho, const int event_type);
X   virtual void release(Entity *const bywho);
X};
X
Xinline
XResource::Resource(const int sz, char *const s)
X{
X   available = sz;
X   resource_name = s;
X   resource_used = 0;
X}
X
X#endif Resource_H
SHAR_EOF
fi
if test -f 'Sim.h'
then
	echo shar: "will not over-write existing file 'Sim.h'"
else
sed 's/^X//' << \SHAR_EOF > 'Sim.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:32 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef Sim_H
X#define Sim_H
X
X#include <std.h>
X#include <stream.h>
X
X#include "Debug.h"
X#include "Event.h"
X#include "Entity.h"
X#include "Resource.h"
X#include "Bin.h"
X
XEvent *cause ( void );
Xshort cancel ( const int eid );
Xdouble simtime ( void );
X
X
X#endif Sim_H
X
SHAR_EOF
fi
if test -f 'SimEntityList.h'
then
	echo shar: "will not over-write existing file 'SimEntityList.h'"
else
sed 's/^X//' << \SHAR_EOF > 'SimEntityList.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:36 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef SimEntityList_H
X#define SimEntityList_H
X
X#include "Entity.h"
X
Xclass SimEntityList;
X
Xclass SimEntityItem {
X   friend class SimEntityList;
Xprivate:
X   SimEntityItem *next;
X   SimEntityItem *prev;
X   Entity * entity;
X
X   SimEntityItem(Entity *const v = 0)
X		{ entity = v; next = prev = 0; }
X};
X
Xclass SimEntityList {
Xprivate:
X   SimEntityItem *head;
X   SimEntityItem *tail;
X   char *listname;
Xpublic:
X   SimEntityList(char *const s = 0)
X		{ head = tail = 0; listname = s; }
X   SimEntityList(Entity *const entity, char *const s)
X		{ head = new SimEntityItem(entity); listname = s; }
X   virtual ~SimEntityList();
X
X   void name(char *const s)	{ listname = s; }
X   char *name() const		{ return listname; }
X   short is_empty()		{ return head == 0; }
X   void print();
X
X   int min_entity_id();
X   int max_entity_id();
X
X   Entity *get()		{ return remove(max_entity_id()); }
X   Entity *remove(const int eid);
X
X   void insert(Entity *const);
X   void append(Entity *const);
X};
X
X
X
X#endif SimEntityList_H
SHAR_EOF
fi
if test -f 'SimEventList.h'
then
	echo shar: "will not over-write existing file 'SimEventList.h'"
else
sed 's/^X//' << \SHAR_EOF > 'SimEventList.h'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:43 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#ifndef SimEventList_H
X#define SimEventList_H
X
X#include "Event.h"
X
Xclass SimEventList;
X
Xclass SimEventItem {
X   friend class SimEventList;
Xprivate:
X   SimEventItem *next;
X   SimEventItem *prev;
X   Event * event;
X
X   SimEventItem(Event *const v = 0)
X		{ event = v; next = prev = 0; }
X};
X
Xclass SimEventList {
Xprivate:
X   SimEventItem *head;
X   SimEventItem *tail;
X   char *listname;
Xpublic:
X   SimEventList(char *const s = 0)
X		{ head = tail = 0; listname = s; }
X   SimEventList(Event *const event, char *const s)
X		{ head = new SimEventItem(event); listname = s; }
X   virtual ~SimEventList();
X
X   void name(char *const s)	{ listname = s; }
X   char *name() const		{ return listname; }
X   short is_empty()		{ return head == 0; }
X   void print();
X
X   int min_event_id();
X   int max_event_id();
X
X   Event *get()			{ return remove(min_event_id()); }
X   Event *remove(const int eid);
X   Event *remove(Entity *const ent);
X
X   void insert(Event *const);
X   void append(Event *const);
X};
X
X
X
X#endif SimEventList_H
SHAR_EOF
fi
if test -f 'Bin.c'
then
	echo shar: "will not over-write existing file 'Bin.c'"
else
sed 's/^X//' << \SHAR_EOF > 'Bin.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:45:38 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include "Bin.h"
X#include "Sim.h"
X
X
Xshort
XBin::take(Entity *bywho, const int event_type)
X{
X   bin_used = 1;
X
X   if ( bywho == 0 )
X      cout << form("** Error: take by null entity\n");
X
X   if ( available > 0 ) {
X      --available;
X      bywho->currentEvent(event_type);
X      return 1;
X   }
X   else {
X      bywho->currentEvent(event_type);
X      blockedQ.append(bywho);
X      return 0;
X   }
X}
X
Xvoid
XBin::give()
X{
X   Entity *entity;
X
X   if ( debug_level(1) ) {
X      cout << form("Releasing bin %s\n", bin_name);
X      cout << "\n---Begin{blockedQ}\n";
X      blockedQ.print();
X      cout << "\n---End{blockedQ}\n";
X   }
X
X   if ( ( entity = blockedQ.get() ) != 0 ) {
X      Event *event = new Event(entity->currentEvent());
X      entity->schedule(0, event);
X   }
X   ++available;
X}
X
Xvoid
XBin::set(const int sz)
X{
X   if ( bin_used ) {
X      cout << form("%s: bin already used. cannot set size\n",
X	 bin_name);
X      exit(-1);
X   }
X   available = sz;
X}
X
SHAR_EOF
fi
if test -f 'Debug.c'
then
	echo shar: "will not over-write existing file 'Debug.c'"
else
sed 's/^X//' << \SHAR_EOF > 'Debug.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:45:43 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include <std.h>
X#include <stream.h>
X
X#include "Debug.h"
X
Xint debug_flag = 0;		/* global debug flag */
X
Xvoid
XfreeStoreException()
X{
X   cout << form("Baby, You're cored.\n");
X   exit(-1);
X}
X
SHAR_EOF
fi
if test -f 'Entity.c'
then
	echo shar: "will not over-write existing file 'Entity.c'"
else
sed 's/^X//' << \SHAR_EOF > 'Entity.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:45:49 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include "Entity.h"
X#include "SimEventList.h"
X#include "Debug.h"
X
X#include "Counter.h"
X
Xstatic Counter timer;
XSimEventList eventlist;
X
XEvent *cause()
X{
X   if ( debug_level(1) ) {
X      cout << "\n---Begin{eventlist}\n";
X      ::eventlist.print();
X      cout << "\n---End{eventlist}\n";
X   }
X
X
X   Event *ev = ::eventlist.get();
X   if ( ev == 0 ) return 0;
X
X   if ( ev->eventTime() > ::timer() ) 
X      ::timer.set(ev->eventTime());
X
X   return ev;
X}
X
Xshort cancel(const int eid)
X{
X   Event *ev = ::eventlist.remove(eid);
X
X   if ( ev == 0 ) return 0;
X   else {
X      delete ev;
X      return 1;
X   }
X}
X
Xdouble simtime()
X{
X   return timer();
X}
X
XEntity::Entity(char *const s)
X{
X   static int eid = 0;
X
X   entity_name = s, entity_id = eid++;
X}
X
Xvoid
XEntity::schedule(const double delay, Event *const ev)
X{
X   if ( delay < 0 ) {
X      cout << form("%s: invalid delay %g\n", entity_name, delay);
X      exit(-1);
X   }
X   ev->scheduled_by(this);
X   ev->eventTime(::timer() + delay);
X
X   ::eventlist.append(ev);
X}
X
SHAR_EOF
fi
if test -f 'Event.c'
then
	echo shar: "will not over-write existing file 'Event.c'"
else
sed 's/^X//' << \SHAR_EOF > 'Event.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:45:53 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include "Event.h"
X
XEvent::Event(const int ev_type)
X{
X   static int e_id = 0;
X
X   event_type = ev_type; event_id = e_id++;
X}
X
SHAR_EOF
fi
if test -f 'Resource.c'
then
	echo shar: "will not over-write existing file 'Resource.c'"
else
sed 's/^X//' << \SHAR_EOF > 'Resource.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:45:56 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include "Resource.h"
X#include "Sim.h"
X#include "SimEventList.h"
X
Xextern SimEventList eventlist;
X
Xshort
XResource::reserve(Entity *bywho, const int event_type)
X{
X   resource_used = 1;
X
X   if ( bywho == 0 )
X      cout << form("** Error: reserve by null entity\n");
X
X   bywho->currentEvent(event_type);
X   bywho->afterTime = 0;
X
X   if ( available > 0 ) {
X      --available;
X      servedQ.append(bywho);
X      return 1;
X   }
X   else {
X      blockedQ.append(bywho);
X      return 0;
X   }
X}
X
Xshort
XResource::preempt(Entity *bywho, const int event_type)
X{
X   resource_used = 1;
X
X   if ( bywho == 0 )
X      cout << form("** Error: preempt by null entity\n");
X
X   bywho->currentEvent(event_type);
X   bywho->afterTime = 0;
X
X   if ( available > 0 ) {
X      --available;
X      servedQ.append(bywho);
X      return 1;
X   }
X   else {
X      Entity *minPrioEnt = servedQ.remove(servedQ.min_entity_id());
X      if ( minPrioEnt->priority() >= bywho->priority() ) { // no preempt
X	 blockedQ.append(bywho);
X	 servedQ.append(minPrioEnt);
X	 return 0;
X      }
X      else { // preempt
X	 servedQ.append(bywho);
X	 Event *stopped = ::eventlist.remove(minPrioEnt);
X	 if ( stopped == 0 ) {
X	    cout << form("** Error: no events for preempted entity\n");
X	    return 0;
X	 }
X	 minPrioEnt->afterTime = stopped->eventTime() - simtime();
X	 minPrioEnt->currentEvent(stopped->type());
X	 blockedQ.insert(minPrioEnt);
X         return 1;
X      }
X   }
X}
X
Xvoid
XResource::release(Entity *const bywho)
X{
X   Entity *entity;
X
X   if ( bywho == 0 )
X      cout << form("** Error: release by null entity\n");
X
X   if ( debug_level(1) ) {
X      cout << form("Releasing resource %s\n", resource_name);
X      cout << "\n---Begin{blockedQ}\n";
X      blockedQ.print();
X      cout << "\n---End{blockedQ}\n";
X   }
X
X   if ( servedQ.remove(bywho->id()) == 0 )
X      cout << form("** Error: release without reserve\n");
X
X   if ( ( entity = blockedQ.get() ) != 0 ) {
X      Event *event = new Event(entity->currentEvent());
X      entity->schedule(entity->afterTime, event);
X   }
X   ++available;
X}
X
Xvoid
XResource::set(const int sz)
X{
X   if ( resource_used ) {
X      cout << form("%s: resource already used. cannot set size\n",
X	 resource_name);
X      exit(-1);
X   }
X   available = sz;
X}
X
SHAR_EOF
fi
if test -f 'Sim.c'
then
	echo shar: "will not over-write existing file 'Sim.c'"
else
sed 's/^X//' << \SHAR_EOF > 'Sim.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:45:59 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include "Counter.h"
X
X#include "Sim.h"
X#include "SimEventList.h"
X
X
Xstatic Counter timer;
Xstatic SimEventList eventlist;
X
XEvent *cause()
X{
X   if ( debug_level(1) ) {
X      cout << "\n---Begin{eventlist}\n";
X      ::eventlist.print();
X      cout << "\n---End{eventlist}\n";
X   }
X
X
X   Event *ev = ::eventlist.get();
X   if ( ev == 0 ) return 0;
X
X   if ( ev->eventTime() > ::timer() ) 
X      ::timer.set(ev->eventTime());
X
X   return ev;
X}
X
Xshort cancel(const int eid)
X{
X   Event *ev = ::eventlist.remove(eid);
X
X   if ( ev == 0 ) return 0;
X   else {
X      delete ev;
X      return 1;
X   }
X}
X
Xdouble simtime()
X{
X   return timer();
X}
X
XEntity::Entity(char *const s)
X{
X   static int eid = 0;
X
X   entity_name = s, entity_id = eid++;
X}
X
Xvoid
XEntity::schedule(const double delay, Event *const ev)
X{
X   if ( delay < 0 ) {
X      cout << form("%s: invalid delay %g\n", entity_name, delay);
X      exit(-1);
X   }
X   ev->scheduled_by(this);
X   ev->eventTime(::timer() + delay);
X
X   ::eventlist.append(ev);
X}
X
Xshort
XResource::reserve(Entity *bywho, const int event_type)
X{
X   resource_used = 1;
X
X   if ( bywho == 0 )
X      cout << form("** Error: reserve by null entity\n");
X
X   bywho->currentEvent(event_type);
X   bywho->afterTime = 0;
X
X   if ( available > 0 ) {
X      --available;
X      servedQ.append(bywho);
X      return 1;
X   }
X   else {
X      blockedQ.append(bywho);
X      return 0;
X   }
X}
X
Xshort
XResource::preempt(Entity *bywho, const int event_type)
X{
X   resource_used = 1;
X
X   if ( bywho == 0 )
X      cout << form("** Error: preempt by null entity\n");
X
X   bywho->currentEvent(event_type);
X   bywho->afterTime = 0;
X
X   if ( available > 0 ) {
X      --available;
X      servedQ.append(bywho);
X      return 1;
X   }
X   else {
X      Entity *minPrioEnt = servedQ.remove(servedQ.min_entity_id());
X      if ( minPrioEnt->priority() >= bywho->priority() ) { // no preempt
X	 blockedQ.append(bywho);
X	 servedQ.append(minPrioEnt);
X	 return 0;
X      }
X      else { // preempt
X	 servedQ.append(bywho);
X	 Event *stopped = ::eventlist.remove(minPrioEnt);
X	 if ( stopped == 0 ) {
X	    cout << form("** Error: no events for preempted entity\n");
X	    return 0;
X	 }
X	 minPrioEnt->afterTime = stopped->eventTime() - simtime();
X	 minPrioEnt->currentEvent(stopped->type());
X	 blockedQ.insert(minPrioEnt);
X	 delete stopped;
X         return 1;
X      }
X   }
X}
X
Xvoid
XResource::release(Entity *const bywho)
X{
X   Entity *entity;
X
X   if ( bywho == 0 )
X      cout << form("** Error: release by null entity\n");
X
X   if ( debug_level(1) ) {
X      cout << form("Releasing resource %s\n", resource_name);
X      cout << "\n---Begin{blockedQ}\n";
X      blockedQ.print();
X      cout << "\n---End{blockedQ}\n";
X   }
X
X   if ( servedQ.remove(bywho->id()) == 0 )
X      cout << form("** Error: release without reserve\n");
X
X   if ( ( entity = blockedQ.get() ) != 0 ) {
X      Event *event = new Event(entity->currentEvent());
X      entity->schedule(entity->afterTime, event);
X      if ( entity->afterTime == 0 ) ++available;
X   }
X   else ++available;
X}
X
Xvoid
XResource::set(const int sz)
X{
X   if ( resource_used ) {
X      cout << form("%s: resource already used. cannot set size\n",
X	 resource_name);
X      exit(-1);
X   }
X   available = sz;
X}
X
SHAR_EOF
fi
if test -f 'SimEntityList.c'
then
	echo shar: "will not over-write existing file 'SimEntityList.c'"
else
sed 's/^X//' << \SHAR_EOF > 'SimEntityList.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:03 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include <stream.h>
X
X#include "SimEntityList.h"
X
X
XSimEntityList::~SimEntityList()
X{
X   SimEntityItem *listnode = head;
X
X   while ( listnode ) {
X      SimEntityItem *temp = listnode;
X
X      listnode = listnode->next;
X      delete temp;
X   }
X   head = tail = 0;
X}
X
Xvoid
XSimEntityList::insert(Entity *const entity)
X{
X   SimEntityItem *listnode = new SimEntityItem(entity);
X   listnode->next = head;
X   if ( head ) head->prev = listnode;
X   else tail = listnode;
X   head = listnode;
X}
X
Xvoid
XSimEntityList::append(Entity *const entity)
X{
X   SimEntityItem *listnode = new SimEntityItem(entity);
X   listnode->prev = tail;
X   if ( tail ) tail->next = listnode;
X   else head = listnode;
X   tail = listnode;
X}
X
XEntity *
XSimEntityList::remove(const int eid)
X{
X   SimEntityItem *listnode = head;
X   SimEntityItem *temp;
X   Entity * gotcha = 0;
X
X   while ( listnode ) {
X      if ( (listnode->entity)->id() == eid ) {
X	 gotcha = listnode->entity;
X	 temp = listnode;
X         if ( listnode->prev != 0 )
X            (listnode->prev)->next = listnode->next;
X         else head = listnode->next;
X         if ( listnode->next != 0 )
X            (listnode->next)->prev = listnode->prev;
X	 else tail = listnode->prev;
X         listnode = listnode->next;
X         delete temp;
X	 break;
X      }
X      else listnode = listnode->next;
X   }
X   return gotcha;
X}
X
Xint
XSimEntityList::max_entity_id()
X{
X   SimEntityItem *listnode = head;
X
X   if ( head == 0 ) return 0;
X
X   int max = (head->entity)->priority();
X   int eid = (head->entity)->id();
X   while ( listnode ) {
X      if ( (listnode->entity)->priority() > max ) {
X	 max = (listnode->entity)->priority();
X	 eid = (listnode->entity)->id();
X      }
X      listnode = listnode->next;
X   }
X   return eid;
X}
X
Xint
XSimEntityList::min_entity_id()
X{
X   SimEntityItem *listnode = head;
X
X   if ( head == 0 ) return 0;
X
X   int min = (head->entity)->priority();
X   int eid = (head->entity)->id();
X   while ( listnode ) {
X      if ( (listnode->entity)->priority() < min ) {
X	 min = (listnode->entity)->priority();
X	 eid = (listnode->entity)->id();
X      }
X      listnode = listnode->next;
X   }
X   return eid;
X}
X
Xvoid
XSimEntityList::print()
X{
X   if ( listname != 0 ) cout << listname << ":\n";
X
X   if ( head == 0 ) {
X      cout << "[ empty ]\n";
X      return;
X   }
X
X   cout << "[ ";
X
X   SimEntityItem *listnode = head;
X   const int lineLength = 16;
X   int cnt = 0;
X   while ( listnode != 0 ) {
X      if ( ++cnt % lineLength == 1 && cnt != 1 )
X	 cout << "\n  ";
X      /* print list->entry at this point */
X      cout << form("0x%x (%g) ",
X	 (listnode->entity)->id(), (listnode->entity)->priority());
X      listnode = listnode->next;
X   }
X   cout << "]\n";
X}
X
SHAR_EOF
fi
if test -f 'SimEventList.c'
then
	echo shar: "will not over-write existing file 'SimEventList.c'"
else
sed 's/^X//' << \SHAR_EOF > 'SimEventList.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:06 $ $Revision: 1.1 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X#include <stream.h>
X
X#include "SimEventList.h"
X
X
XSimEventList::~SimEventList()
X{
X   SimEventItem *listnode = head;
X
X   while ( listnode ) {
X      SimEventItem *temp = listnode;
X
X      listnode = listnode->next;
X      delete temp;
X   }
X   head = tail = 0;
X}
X
Xvoid
XSimEventList::insert(Event *const event)
X{
X   SimEventItem *listnode = new SimEventItem(event);
X   listnode->next = head;
X   if ( head ) head->prev = listnode;
X   else tail = listnode;
X   head = listnode;
X}
X
Xvoid
XSimEventList::append(Event *const event)
X{
X   SimEventItem *listnode = new SimEventItem(event);
X   listnode->prev = tail;
X   if ( tail ) tail->next = listnode;
X   else head = listnode;
X   tail = listnode;
X}
X
XEvent *
XSimEventList::remove(const int eid)
X{
X   SimEventItem *listnode = head;
X   SimEventItem *temp;
X   Event * gotcha = 0;
X
X   while ( listnode ) {
X      if ( (listnode->event)->id() == eid ) {
X	 gotcha = listnode->event;
X	 temp = listnode;
X         if ( listnode->prev != 0 )
X            (listnode->prev)->next = listnode->next;
X         else head = listnode->next;
X         if ( listnode->next != 0 )
X            (listnode->next)->prev = listnode->prev;
X	 else tail = listnode->prev;
X         listnode = listnode->next;
X         delete temp;
X	 break;
X      }
X      else listnode = listnode->next;
X   }
X   return gotcha;
X}
X
XEvent *
XSimEventList::remove(Entity *const ent)
X{
X   SimEventItem *listnode = head;
X   SimEventItem *temp;
X   Event * gotcha = 0;
X
X   while ( listnode ) {
X      if ( (listnode->event)->scheduled_by() == ent ) {
X	 gotcha = listnode->event;
X	 temp = listnode;
X         if ( listnode->prev != 0 )
X            (listnode->prev)->next = listnode->next;
X         else head = listnode->next;
X         if ( listnode->next != 0 )
X            (listnode->next)->prev = listnode->prev;
X	 else tail = listnode->prev;
X         listnode = listnode->next;
X         delete temp;
X	 break;
X      }
X      else listnode = listnode->next;
X   }
X   return gotcha;
X}
X
Xint
XSimEventList::min_event_id()
X{
X   SimEventItem *listnode = head;
X
X   if ( head == 0 ) return 0;
X
X   double min = (head->event)->eventTime();
X   int eid = (head->event)->id();
X   while ( listnode ) {
X      if ( (listnode->event)->eventTime() < min ) {
X	 min = (listnode->event)->eventTime();
X	 eid = (listnode->event)->id();
X      }
X      listnode = listnode->next;
X   }
X   return eid;
X}
X
Xint
XSimEventList::max_event_id()
X{
X   SimEventItem *listnode = head;
X
X   if ( head == 0 ) return 0;
X
X   double max = (head->event)->eventTime();
X   int eid = (head->event)->id();
X   while ( listnode ) {
X      if ( (listnode->event)->eventTime() > max ) {
X	 max = (listnode->event)->eventTime();
X	 eid = (listnode->event)->id();
X      }
X      listnode = listnode->next;
X   }
X   return eid;
X}
X
Xvoid
XSimEventList::print()
X{
X   if ( listname != 0 ) cout << listname << ":\n";
X
X   if ( head == 0 ) {
X      cout << "[ empty ]\n";
X      return;
X   }
X
X   cout << "[ ";
X
X   SimEventItem *listnode = head;
X   const int lineLength = 16;
X   int cnt = 0;
X   while ( listnode != 0 ) {
X      if ( ++cnt % lineLength == 1 && cnt != 1 )
X	 cout << "\n  ";
X      /* print list->entry at this point */
X      cout << form("0x%x (%g) ",
X	 (listnode->event)->id(), (listnode->event)->eventTime());
X      listnode = listnode->next;
X   }
X   cout << "]\n";
X}
X
SHAR_EOF
fi
if test -f 'Test.c'
then
	echo shar: "will not over-write existing file 'Test.c'"
else
sed 's/^X//' << \SHAR_EOF > 'Test.c'
X/* $Author: ecsv38 $ $Date: 90/08/21 14:46:11 $ $Revision: 1.2 $ */
X/* (c) S. Manoharan  sam at lfcs.edinburgh.ac.uk */
X
X/* Reference --
X at book{MacDo87,
X   author =	"M H MacDougall",
X   year =	"1987",
X   publisher =	"MIT Press",
X   title =	"Simulating Computer Systems: Techniques and Tools"
X}
X-- */
X
X
X#include "Sim.h"
X
X#include <std.h>
X#include <new.h>
X#include <MLCG.h>
X#include <DiscreteUniform.h>
X
X
Xint main(int argc, char **argv)
X{
X   MLCG gen;
X   DiscreteUniform sample(0, 20, &gen);
X
X   int Debug_flag = 0;
X
X
X   set_new_handler(freeStoreException);
X
X   const double MAXTIME = 500;
X
X   Resource server(1, "Server");
X   Entity customer("Customer");
X   const int ARRIVAL = 1;
X   const int DEPART  = 2;
X   const int RESERVE = 3;
X
X   double delay, inst; Event *event;
X
X   Event *ev = new Event(ARRIVAL);
X   customer.schedule(0, ev);
X   while ( simtime() < MAXTIME ) {
X      event = cause(); inst = simtime();
X      if ( event == 0 ) {
X	 cout << form("%s: no more events to process\n", argv[0]);
X	 exit(0);
X      }
X      else cout << form("[%g]\t** event %d (id %d) caused\n",
X	 inst, event->type(), event->id());
X
X      switch ( event->type() ) {
X      case ARRIVAL :
X	 cout << form("[%g]\tArrival\n", inst);
X
X	 ev = new Event(RESERVE);
X	 cout << form("[%g]\tscheduling a RESERVE\n", inst);
X	 customer.schedule(0, ev);
X
X	 ev = new Event(ARRIVAL);
X	 delay = sample();
X	 cout << form("[%g]\tscheduling an ARRIVAL after %g\n",
X	    inst, delay);
X	 customer.schedule(delay, ev);
X
X	 break;
X      case RESERVE :
X	 cout << form("[%g]\tReserve\n", inst);
X	 if ( server.reserve(&customer, event->type()) ) {
X	    ev = new Event(DEPART);
X	    delay = sample();
X	    cout << form("[%g]\tscheduling a DEPART after %g\n",
X	       inst, delay);
X	    customer.schedule(delay, ev);
X	 }
X	 else
X	    cout << form("[%g]\tserver busy now\n", inst);
X	 break;
X      case DEPART :
X	 cout << form("[%g]\tDepart\n", inst);
X	 server.release(&customer);
X	 break;
X      default :
X	 cout << form("%s: invalid event %d detected\n",
X	    argv[0], event->type());
X	 break;
X      }
X
X      delete event;
X   }
X
X   return 0;
X}
SHAR_EOF
fi
exit 0
#	End of shell archive



More information about the Comp.sources.misc mailing list