IMPLEMENTATION MODULE GroupMac; IMPORT SIM, STAT, EVENT, PROCS; FROM SYSTEM IMPORT ADDRESS; FROM Storage IMPORT ALLOCATE, DEALLOCATE; FROM MYINOUT IMPORT WriteString, WriteLn; FROM STAT IMPORT Update; FROM RES IMPORT Resource, Request, Release; FROM EVENT IMPORT EventType, EventNotice, ScheduleNotice, CancelNotice; FROM PROCS IMPORT ProcessType, ScheduleNamed, Delay, Resume, Suspend, CurrentProcess, InstanceState, ProcessState, Terminate; TYPE ParamMach = POINTER TO RECORD (* Parametres d'une machine. *) Gr : Groupe; (* Son Groupe. *) No : Num (* Son numero. *) END; VAR UnRobot, UneMachine : ProcessType; ArriveeRobot : EventType; PROCEDURE Erreur (i : CARDINAL); BEGIN WriteString ("DECISION ILLEGALE DU ROBOT:"); CASE i OF 1 : WriteString (" Reparation sans etre en face d'une mach. fautive.") | 2 : WriteString (" Destination < 1.") | 3 : WriteString (" Destination > Nb. de mach.") END; WriteLn; SIM.Stop; Terminate END Erreur; PROCEDURE Create ( VAR G : Groupe; n, dev : Num; d : Politique; df : DureeFonc; dr : DureeRepar; drm : DureeRepar; r : Resource ); VAR i : Num; Par : ParamMach; BEGIN NEW (G); WITH G^ DO EnPanne := EnsMach {}; FOR i := 1 TO n DO NEW (Par); Par^.Gr := G; Par^.No := i; ScheduleNamed (UneMachine, 0.0, Par, Machine [i]); END; N := n; NbOK := n; Devant := dev; Pos := FLOAT (Devant); Dir := Droite; Decision := d; DFonc := df; DRepar := dr; DReparMan := drm; Reparateur := r; ScheduleNamed (UnRobot, 0.0, G, Robot); STAT.Create (Prod, STAT.Accumulate, "Taux de production"); STAT.Init (Prod); Update (Prod, FLOAT (N)) ; END END Create; PROCEDURE Delete (VAR G : Groupe); (* Recupere tout l'espace occupe par G. *) VAR i : Num; Par : ParamMach; BEGIN WITH G^ DO FOR i := 1 TO N DO Par := ParamMach (PROCS.InstanceAttrib (Machine [i])); DISPOSE (Par); PROCS.Kill (Machine [i]) END; STAT.Delete (Prod); PROCS.Kill (Robot) END; DISPOSE (G) END Delete; PROCEDURE ProcArrivee; (* Evenement : Le robot atteint sa destination. *) VAR G : Groupe; BEGIN G := Groupe (EVENT.Attrib ()); WITH G^ DO Devant := Dest; Resume (Robot) END; END ProcArrivee; PROCEDURE ProcMachine; (* Decrit le comportement d'une machine. *) VAR No : Num; (* Son numero. *) Par : ParamMach; (* Pointeur sur ses parametres. *) BEGIN Par := ParamMach (PROCS.Attrib ()); No := Par^.No; WITH Par^.Gr^ DO (* Groupe auquel elle appartient. *) WHILE TRUE DO Delay (DFonc ()); (* Fin du delai: La mach. tombe en panne. *) DEC (NbOK); INCL (EnPanne, No); Update (Prod, FLOAT (NbOK)); IF InstanceState (Robot) = Suspended THEN Resume (Robot) END; Suspend END (* Reactivation: fin de la reparation. *) END END ProcMachine; PROCEDURE ProcRobot; VAR S : BOOLEAN; G : Groupe; BEGIN G := Groupe (PROCS.Attrib ()); (* Groupe auquel il appartient. *) WITH G^ DO WHILE TRUE DO Dest := Decision (G); IF Dest = 0 THEN (* Repare la machine devant lui. *) IF (Devant = 0) OR (NOT (Devant IN EnPanne)) THEN Erreur (1) END; Delay (DRepar (S)); IF (NOT S) THEN (* La reparation a echoue. *) Request (1, Reparateur); Delay (DReparMan (S)); Release (1, Reparateur) END; Resume (Machine [Devant]); (* Doit s'executer avant la prochaine prise de decision: *) INC (NbOK); EXCL (EnPanne, Devant); Update (Prod, FLOAT (NbOK)) ELSIF Dest = Devant THEN Suspend (* Le robot attend. *) ELSE (* Le robot se deplace. *) IF Dest > N THEN Erreur (3) END; IF FLOAT (Dest) > Pos THEN Dir := Droite ELSE Dir := Gauche END; Devant := 0; TDepart := SIM.Time (); ScheduleNotice (ArriveeRobot, ABS (Pos - FLOAT (Dest)), G, AvisArrivee); Suspend; IF Devant = Dest THEN (* Le robot arrive a destination. *) Pos := FLOAT (Dest) ELSE (* Une machine tombe en panne. *) IF Dir = Droite THEN Pos := Pos + SIM.Time () - TDepart ELSE Pos := Pos - SIM.Time () + TDepart END; CancelNotice (AvisArrivee) END END END END END ProcRobot; BEGIN EVENT.Create (ArriveeRobot, ProcArrivee, "Arrivee du robot"); PROCS.Create (UneMachine, ProcMachine, 2048, "Une machine"); PROCS.Create (UnRobot, ProcRobot, 2048, "Un robot") END GroupMac.