unit simobj; {simulation objects use the clock. When one is initialized, it is linked into a list, so all can be reset and reported on. They have a trace flag, so that tracing can be enabled by particular methods. Reset does not affect the trace flag, but sets a new start time. All objects will have a general description, e.g. TA generation (source) which can be expanded to Airplane landings TA generation (source) by a call to SpecificLabel ('Airplane landings') } {Part of simulation toolboxes, Author Lin Jensen Date Oct. 3 1996 } INTERFACE USES CLOCK, QUEUE; TYPE {The part in common: } str20 = string[20]; simPtr = ^aSimObject; aSimObject = OBJECT (queueElement) Description : string[50]; startTime : REAL; traceFlag : BOOLEAN ; constructor Init (whoAmI : str20); constructor SubInit (whoAmI : str20); {Subsidiary init, without linking for report} procedure Reset; VIRTUAL; {to enable global reset and report} procedure Trace ; procedure Untrace ; procedure Report ; VIRTUAL; procedure SpecificLabel (CallMe : STR20); destructor Destroy; virtual; {allows actual size to be determined} end; ReportList = OBJECT (FIFOQueue) procedure ResetAll; procedure ReportAll; end; VAR Reporter : ReportList; IMPLEMENTATION const banner = '>>> ==================================================== <<<'; {==== COMMON ELEMENTS TO MOST SIMULATION OBJECTS IN OTHER UNITS ======} constructor aSimObject.Init (whoAmI : str20); begin queueElement.Init; {constructor of base type} Description := whoAmI; startTime := TheClock.NOW; traceFlag := FALSE; Reporter.tail_insert (Addr(self)); {put self in list} end; constructor aSimObject.SubInit (whoAmI : str20); begin queueElement.Init; {constructor of base type} Description := whoAmI; startTime := TheClock.NOW; traceFlag := FALSE; end; procedure aSimObject.SpecificLabel (callme:str20); type ba = array [0..50] of char; var len, start, c, old : byte; p : ^ba; begin { Description := ConCat ( CallMe, ' ', Description);} {but concat uses too much stack space, so we do it char by char:} start := length(callme) + 2; len := length(callme)+length(description)+1; if len > 50 then len := 50; p := addr(description); p^[0] := chr(len); old := len-start+1; for c := len downto start do begin p^[c] := description[old]; dec (old); end; p^[start-1] := ' '; for c := 1 to start-2 do P^[c] := callme[c]; end; procedure aSimObject.Trace ; begin WRITELN; WRITE (' * * * * * Trace of ',Description, ' switched ON at '); WRITELN (TheClock.NOW:7:2); WRITELN; traceFlag := TRUE; end; procedure aSimObject.Untrace ; begin WRITELN; WRITE (' * * * * * Trace of ',Description, ' switched OFF at '); WRITELN (TheClock.NOW:7:2); WRITELN; traceFlag := FALSE; end; procedure aSimObject.Reset ; begin WRITE (Description, ' statistics reset at '); TheClock.rite; WriteLN; startTime := TheClock.TellTime; end; procedure aSimObject.Report; begin WRITELN('- - - - - - - - - -'); WRITE ('Report on ',Description, ', last reset at', StartTime:8:2); WRITELN (' Since then, '); end; destructor aSimObject.Destroy; var dmy:ElementPtr; begin dmy := reporter.remove (addr(self)); if dmy <> Nil then writeln ('Canceling report on ', Description); end; {Don't want reporter to use me any more!} {================= Global reporting !! +===========} procedure ReportList.ResetAll; var so : SimPtr; begin Writeln (banner); Write (' GLOBAL RESET AT ' ); TheClock.rite; Writeln; Writeln (banner); so := simPtr(HeadQ); while so <> Nil do begin so^.reset; so := simPtr(so^.next); end; Writeln ; end; procedure ReportList.ReportAll; var so : SimPtr; begin Writeln (banner); Write (' SIMULATION REPORT AT ' ); TheClock.rite; Writeln; Writeln (banner); so := simPtr(HeadQ); while so <> Nil do begin so^.report; so := simPtr(so^.next); end; Writeln (banner); end; BEGIN {Initialization code} Reporter.Init; End.