program ManuelsShop ; { A single queue, single or multiple server queueing model } { the PROCESS-oriented version using the process manager toolbox ! } { one customer STARTs, each starts the next. uses a SEMAPHORE for queuing} {Adapted from Wolfgang Kreutzer, System Simulation, programming styles and Languages, 1986, ISBN 0-201-12914-0, p 245 ff.} {the OOP version for turbo Pascal 6.0 and up, Adapted by Lin Jensen, October 1996. New Features: All objects are implemented as objects. Global Reset and Report implemented in SIMOBJ. } USES clock, queue,simobj, mcobj, statobj, qnetobj, coproc, proc_man, usebios; const NoDelay = 0.0; AlongNumber = MAXINT; PreSimulationSamples = 500; ExperimentSamples = 1000; type PosIntType = WORD; {UNsigned numbers} custptr = ^ customer; customer = object (procdescr) procedure lifecycle; virtual; end; var numberServers : integer; {vary the number of clerks in shop} { Declared and initialized in units: TheClock -- in CLock TheMonitor -- in Proc_man Reporter : ReportList; -- in SIMOBJ } Arrivals, Service : RandomNegExp; {source and sink are really counters!} Source : Counter; Sink : Counter; { Q : aQueueType; -- replaced by semaphore } { this type had statistics which are similar to a MEASURE } Q : SEMQUEUE; { processes wait for service here } Manuel : aServerType; { gathers utilization statistics } FlowTime : Histogram; { bar graph of time spent in shop } {------------- CUSTOMER LIFE CYCLE -----------------------------} procedure customer.lifecycle; var birthTime : REAL; romeo : custptr; {creates incoming customers and puts them in a queue in front of Manuel} begin {random arrival} SLEEP_FOR ( Arrivals.NegExp ); birthTime := theClock.TellTime; {record time of entry into shop} { create next customer} NEW (romeo, Init('ROMEO',GetNumber+1)); resume(romeo); Source.Update; {put him into the Q and schedule a start event} Q.WAIT; Manuel.SeizeServer (1); { turn attention to waiting customer} {diagnose degree of lovesickness, mix, and hand over remedy; accept donation } SLEEP_FOR ( Service.NegExp ); {time required for service} Manuel.ReleaseServer (1); Q.SIGNAL; FlowTime.Update (TheClock.TellTime - BirthTime); {time in shop} Sink.Update ; Monitor.RecordSample; { TERMINATE;} {This Customer dissappears} end; { of Customer Life Cycle -------------------------------------------} procedure ReadAndInitialize; { initiates the model's entities ! } var romeo : custptr; begin ClrScr; prompt ('Manuel''s shop. How many servers? '); readln (numberServers); Arrivals.Init (12345, 0.8*numberServers); Service.Init (67891, 1.0 ); Source.Init; Source.SpecificLabel ('Source Creation'); Sink.Init; Sink.SpecificLabel ('Sink Departure'); Q.Init (numberServers); {how many at a time!} Manuel.Init (numberServers); Manuel.SpecificLabel ('Manuel''s performance'); FlowTime.Init ( 0, 25, 10 ); FlowTime.SpecificLabel ('Customers'' Time in Shop'); { ScheduleEvent -- first hello } {ready first customer} NEW (romeo, Init('ROMEO', 0)); resume(romeo); end; {Procedure RunModelForSamples -- replaced by RUNSIMULATION } begin { * * * * * Body of MAIN program * * * * * } ReadAndInitialize; Monitor.RunSIMULATION (aLongNumber, PreSimulationSamples); Monitor.Report; {see processes at reset} WaitKeyPress; Reporter.ResetALL; Monitor.RunSIMULATION (aLongNumber, ExperimentSamples); WaitKeyPress; Reporter.ReportALL; WaitKeyPress; end.