An M/M/1 queue has an exponential inter-arrival and service time and a single server. We are interested in the statistics of the size of the queue and the waiting times of a customer, with varying means for the inter-arrival times and service times. Consider the following process-oriented simulation program.
We first include the library and define the phases for a customer. The simulation object, the resource, the generators, the queue and the means for the arrival and service times, as well as the customer and server entities are declared.
#include <sim/sim.h> enum {ARRIVAL,DEPARTURE}; simulation* sim; resource* r; queue* q; double meanarrival,meanservice; // mean inter-arrival and service time generator* g; class customer : public entity { public : customer(int ph); virtual int operator()(); int arrival(); int departure(); }; class server : public entity { public : server(); virtual int operator()(); };
A customer arrives or departs, so it receives a phase, when created. The behavior of the entity customer is implemented in its application operator. When a customer arrives, first a new customer is scheduled to arrive. We take the inter-arrival time to be exponential, with meanarrival as the mean inter-arrival time. Then the customer is appended to the queue. When the customer is served the resource is acquired by the server, a departing customer then releases the resource and is terminated. The default amount of 1 is released and acquired each time.
customer::customer(int ph) : entity(ph) { } int customer::operator()() { switch (phase()) { case ARRIVAL : return arrival(); case DEPARTURE : return departure(); } return FALSE; } int customer::arrival() { customer* c = new customer(ARRIVAL); // schedule new customer sim -> schedule(c,(g -> exponential(meanarrival))); q -> append(this); // append to the queue return OK; } int customer::departure() { r -> release(); // release the resource sim -> terminate(this); // terminate this customer return OK; }
The behavior of the entity server does not depend on a phase. Every time it is activated, it takes a customer from the queue if possible, i.e. if the queue is not empty and if the required amount of the resource (in this case the default amount of 1) is available. If it takes a customer, it acquires the resource, adjusts the phase of the customer to DEPARTURE and schedules the customer to depart, after it has been served.
server::server() : entity() { } int server::operator()() { // can we serve a customer ? if ( (!(q -> empty())) && (r -> available()) ) { customer* c = (customer *)q -> removefront(); // take first r -> acquire(); // acquire the resource sim -> schedule(c,g -> exponential(meanservice)); c -> phase(DEPARTURE); // adjust phase and schedule departing } return OK; }
The function application::main creates the queue and two histograms, that are used for generating reports on the size of the queue and the waiting times of a customer. A resource with an initial amount of 1 is created. The simulation is set up by scheduling a customer to arrive immediately and making the server conditional. The server is never passivated, so it stays on the conditional list for the entire simulation and is activated, whenever a customer is. If the simulation has various queues and servers the server should be scheduled whenever a customer departs to make the program more efficient.
class application : public session { public : application(int argc,char** argv); int main(); }; application::application(int argc,char** argv) : session(argc,argv,"M/M/1-queue") {} int application::main() { cout << "mean time between two arrival events" << endl; cin >> meanarrival; cout << "mean time between two service events" << endl; cin >> meanservice; // create objects and reports sim = new simulation(); g = new generator(8,2,9); histogram* h1 = new histogram(".h1","-type weighted -form statistics -title size"); histogram* h2 = new histogram(".h2","-type frequency -form statistics -title waitingtimes"); tk -> pack(h1); tk -> pack(h2); tk -> update(); q = new queue(); q -> reportsize(h1); // generate a report on the size of the queue q -> reportwaiting(h2); // generate a report on waiting times r = new resource(1); // set up and run the simulation customer* c = new customer(ARRIVAL); sim -> schedule(c,0.0); // initially a customer arrives server* s = new server(); sim -> hold(s); // the server is conditional sim -> run(10000.0); delete h1; delete h2; delete q; delete sim; return 0; } main(int argc,char** argv) { session *s = new application(argc,argv); // create the session return s -> run(); // start the session }