IMPLEMENTATION MODULE GENEP; (************************************************************************** Environnement : Solaris 2.3 Mcs Modula-2. ------------- Programmeur : Pierre L'Ecuyer ------------ ***************************************************************************) FROM Storage IMPORT ALLOCATE, DEALLOCATE; FROM MYINOUT IMPORT WriteString, WriteLn, WriteCard; FROM NUM IMPORT WriteLR; FROM EVENT IMPORT EventType, EventNotice, CancelNotice; FROM PROCS IMPORT ProcessType; FROM RAND IMPORT Gen; FROM RAND1 IMPORT Expon; FROM STAT IMPORT Block, NumberObs, Minimum, Maximum, Average, StandardDev; FROM SYSTEM IMPORT ADDRESS; IMPORT SIM, EVENT, PROCS, STAT; CONST LongName = 32; TYPE ArrivalType = (Event, Process); ArrivalProcess = POINTER TO InfoArrivalProcess; InfoArrivalProcess = RECORD CASE Kind : ArrivalType OF Event : TypeE : EventType; (* Type of events to generate. *) | Process : TypeP : ProcessType (* Type of processes to generate. *) END; CASE Poisson : BOOLEAN OF TRUE : MeanTime : LONGREAL; (* Mean time between arrivals. *) GenNumber : Gen (* Generator number used. *) | FALSE : Proc : DelayProc (* Generates times between arrivals. *) END; Param : ADDRESS; (* Parameter associated. *) NbMax : LONGCARD; (* Max. number af arrivals. *) N : LONGCARD; (* Number of arrivals to date. *) Notice : EventNotice; (* Event to produce the next arrival. *) Stat : BOOLEAN; (* TRUE if stats. are collected. *) TInit : LONGREAL; (* Instant de la derniere init. du *) (* blocs stat. *) StatsOnDelay : Block; (* Stat. on times between arrivals. *) LastTime : LONGREAL; (* Time of last arrival. *) Descriptor : ARRAY [0..LongName-1] OF CHAR END; VAR OneArrival : EventType; (* An arrival occurs. *) (******************************************************************************) PROCEDURE Error (Number : CARDINAL); BEGIN WriteString ('***** ERROR from module ARRIV, at time '); WriteLR (SIM.Time (), 10, 3, 2); WriteString (' ***** ' ); WriteLn; CASE Number OF 0 : WriteString ("Referencing to an undefined arrival process.") END; WriteLn; WriteLn; HALT END Error; PROCEDURE Create ( VAR A : ArrivalProcess; Name : ARRAY OF CHAR ); VAR n, i : INTEGER; BEGIN NEW (A); WITH A^ DO N := 0; n := HIGH (Name); IF n >= LongName THEN n := LongName - 1 END; FOR i := 0 TO n DO Descriptor [i] := Name [i] END; FOR i := n+1 TO LongName - 1 DO Descriptor [i] := " " END; Stat := FALSE END END Create; PROCEDURE ProcOneArrival; (* Procedure qui s'execute lors d'une arrivee pour A. *) VAR A : ArrivalProcess; Delay : LONGREAL; BEGIN A := EVENT.Attrib (); WITH A^ DO CASE Kind OF Event : EVENT.ScheduleNext (TypeE, Param); | Process : PROCS.ScheduleNext (TypeP, Param) END; IF Stat THEN STAT.Update (StatsOnDelay, SIM.Time () - LastTime) END; LastTime := SIM.Time (); INC (N); IF ((NbMax = 0) OR (N < NbMax)) THEN IF Poisson THEN Delay := Expon (MeanTime, GenNumber) ELSE Delay := Proc () END; EVENT.ScheduleNotice (OneArrival, Delay, A, Notice) END END END ProcOneArrival; PROCEDURE StartPoissonArrivalsE ( A : ArrivalProcess; E : EventType; Par : ADDRESS; Mean : LONGREAL; g : Gen; Nmax : LONGCARD ); BEGIN WITH A^ DO Kind := Event; TypeE := E; Poisson := TRUE; NbMax := Nmax; N := 0; MeanTime := Mean; GenNumber := g; Param := Par; LastTime := SIM.Time (); EVENT.ScheduleNotice (OneArrival, Expon (Mean, g), A, Notice) END END StartPoissonArrivalsE; PROCEDURE StartArrivalsE ( A : ArrivalProcess; E : EventType; Par : ADDRESS; D : DelayProc; Nmax : LONGCARD ); BEGIN WITH A^ DO Kind := Event; TypeE := E; Poisson := FALSE; Proc := D; NbMax := Nmax; N := 0; Param := Par; LastTime := SIM.Time (); EVENT.ScheduleNotice (OneArrival, D (), A, Notice) END END StartArrivalsE; PROCEDURE StartPoissonArrivalsP ( A : ArrivalProcess; T : ProcessType; Par : ADDRESS; Mean : LONGREAL; g : Gen; Nmax : LONGCARD ); BEGIN WITH A^ DO Kind := Process; TypeP := T; Poisson := TRUE; NbMax := Nmax; N := 0; MeanTime := Mean; GenNumber := g; Param := Par; LastTime := SIM.Time (); EVENT.ScheduleNotice (OneArrival, Expon (Mean, g), A, Notice) END END StartPoissonArrivalsP; PROCEDURE StartArrivalsP ( A : ArrivalProcess; T : ProcessType; Par : ADDRESS; D : DelayProc; Nmax : LONGCARD ); BEGIN WITH A^ DO Kind := Process; TypeP := T; Poisson := FALSE; Proc := D; NbMax := Nmax; N := 0; Param := Par; LastTime := SIM.Time (); EVENT.ScheduleNotice (OneArrival, D (), A, Notice) END END StartArrivalsP; PROCEDURE StopArrivals ( A : ArrivalProcess ); BEGIN IF A = NIL THEN Error (0) END; EVENT.CancelNotice (A^.Notice) END StopArrivals; PROCEDURE CollectStat ( A : ArrivalProcess ); BEGIN IF A = NIL THEN Error (0) END; WITH A^ DO Stat := TRUE; TInit := SIM.Time (); STAT.Create (StatsOnDelay, STAT.Tally, Descriptor) END END CollectStat; PROCEDURE StatDelay ( A : ArrivalProcess ) : Block; BEGIN RETURN A^.StatsOnDelay END StatDelay; PROCEDURE NbArriv ( A : ArrivalProcess ) : LONGCARD; BEGIN RETURN A^.N END NbArriv; PROCEDURE Report ( A : ArrivalProcess ); BEGIN IF A = NIL THEN Error (0) END; WITH A^ DO IF Stat THEN WriteLn; WriteString ("REPORT ON ARRIVAL PROCESS : "); WriteString (Descriptor); WriteLn; WriteString (' From time '); WriteLR (TInit, 7, 2, 2); WriteString (' to time '); WriteLR (SIM.Time (), 10, 2, 2); WriteLn; WriteString (' min max average '); WriteString ('standard dev. nb. Obs.'); WriteLn; WriteString (' Inter Arr. '); WriteLR (Minimum (StatsOnDelay), 9, 3, 2); WriteString (' '); WriteLR (Maximum (StatsOnDelay), 10, 3, 2); WriteString (' '); WriteLR (Average (StatsOnDelay), 10, 3, 2); WriteString (' '); WriteLR (StandardDev (StatsOnDelay), 10, 3, 2); WriteCard (NumberObs (StatsOnDelay), 11); WriteLn END END END Report; PROCEDURE Delete (VAR A : ArrivalProcess); BEGIN IF A^.Stat THEN STAT.Delete(A^.StatsOnDelay) END; DISPOSE (A) END Delete; BEGIN EVENT.Create (OneArrival, ProcOneArrival, "One arrival") END GENEP.