with Ada.Real_Time; use Ada.Real_Time; with Ada.Task_Identification; use Ada.Task_Identification; with Ada.Command_Line; use Ada.Command_Line; with Text_Io; use Text_Io; procedure Add_Reset is function Task_Name_Image return String is X : constant String := Image(Current_Task); begin for J in reverse X'Range loop if X(J) = '_' then return X(X'First .. J - 1); end if; end loop; return X; end Task_Name_Image; protected X is procedure Read (Out_X: out Integer); procedure Increment; procedure Clear; private Reset_X : Integer := 0; Increment_By : Integer := 1; The_X : Integer; -- can't be set to 'Reset_X' here; -- set before 'Execute' end X; protected body X is procedure Read (Out_X: out Integer) is begin Out_X := The_X; end Read; procedure Increment is begin The_X := The_X + Increment_By; end Increment; procedure Clear is begin The_X := Reset_X; end Clear; end X; protected Warning is private The_Warning : Boolean := False; procedure Enable; end Warning; protected body Warning is procedure Enable is begin The_Warning := True; Put_Line("Warning!"); end Enable; end Warning; procedure Execute is task Reset is entry Halt; end Reset; task Add_One is entry Halt; end Add_One; task Watch_Dog; task body Reset is Task_Name : constant String := Task_Name_Image; Compare_To : constant Integer := 50; Next : Time; Period : constant Time_Span := Milliseconds(1000); Check_X : Integer; Running : Boolean := True; begin Next := Clock; while Running loop X.Read(Check_X); if Check_X = Compare_To then Put_Line(Task_Name & ": X is above " & Integer'Image(Compare_To) & ". Clearing it."); X.Clear; end if; Next := Next + Period; select accept Halt do Put_Line(Task_Name & ": I'm done reseting."); Running := False; end Halt; or delay until Next; end select; end loop; end Reset; task body Add_One is Task_Name : constant String := Task_Name_Image; Add_Message : constant String := Task_Name & ": +1"; Running : Boolean := True; Next : Time; Period : constant Time_Span := Milliseconds(20); Try_Hit : constant Boolean := (Argument_Count = 1 and then Argument(1) = "-h"); begin Next := Clock; while Running loop if not Try_Hit then Put_Line(Add_Message); X.Increment; end if; Next := Next + Period; select accept Halt do Put_Line(Task_Name & ": I'm done adding."); Running := False; end Halt; or delay until Next; if Running and Try_Hit then Put_Line(Add_Message); X.Increment; end if; end select; end loop; end Add_One; task body Watch_Dog is Task_Name : constant String := Task_Name_Image; Next : Time; Period : constant Time_Span := Milliseconds(100); Check_X : Integer; Compare_Above : constant Integer := 50; begin Next := Clock; loop X.Read(Check_X); if Check_X > Compare_Above then Put_Line(Task_Name & ": X > " & Integer'Image(Compare_Above) & ". Sending a warning. Telling all to stop."); Warning.Enable; Add_One.Halt; Reset.Halt; exit; end if; Next := Next + Period; delay until Next; end loop; end Watch_Dog; begin null; end Execute; begin Put_Line("System is up and running."); Put_Line("Note: exit anytime with Ctrl-C."); X.Clear; Execute; end Add_Reset;