// C++/CSIM Model two servers with JSQ policy

#include "cpp.h"			// class definitions

#define NARS 50000
#define IAR_TM 2.0
#define SRV_TM 1.0

event done("done");			// the event named done
facility_set   f("facility", 2);        // the facility named f
table tbl("resp tms");			// table of response times
qhistogram qtbl_a("num in sys", 10l);	// qhistogram of number in system
qhistogram qtbl_b("num in sys", 10l);	// qhistogram of number in system
int cnt;				// count of remaining processes

void traffic();
void customer();

extern "C" void sim(int, char **);

void sim(int argc, char *argv[])
{
	set_model_name("Two Servers with JSQ");
	create("sim");

	cnt = NARS;
	
	traffic();			// generate traffic

	done.wait();			// wait for last customer to depart
	report();			// model report
	mdlstat();			// model statistics
}

void traffic()
{
	int i;

	create("traffic");    


        for (i=1; i<= NARS;i++){ 
              hold(expntl(IAR_TM));
	      customer();
        }
}
	
void customer()				// arriving customer
{
	double t1;
        int position;

	create("cust");
	t1 = clock;			// record start time

        // determine position to join
        if ((f[0].qlength() < f[1].qlength()))
              position = 0;
        else if ((f[0].qlength() > f[1].qlength()))
              position = 1; 
        else { // randomly choose a server to join
           if ( uniform(0.0,1.0) < 0.5 )
                position = 0;
           else position = 1;
        }
 
        if ( position == 0){
	    qtbl_a.note_entry();		// note arrival
	    f[0].reserve();			// reserve facility
		hold(expntl(SRV_TM));	// service interval
	    f[0].release();			// release facility
	    qtbl_a.note_exit();		// note departure
        }
        else {
	    qtbl_b.note_entry();		// note arrival
	    f[1].reserve();			// reserve facility
		hold(expntl(SRV_TM));	// service interval
	    f[1].release();			// release facility
	    qtbl_b.note_exit();		// note departure
        }
	tbl.record(clock - t1);		// record response time
	if(--cnt == 0)
		done.set();		// if last customer, set done
}


