🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: de.comp.lang.pascal
Article #27

Zeitvariable II - C++ und Pascal

#27
From: Alexander E. Schmidt
Date: Mon, 08 Jan 1996 22:28
202 lines
7073 bytes
Hallo,

vor einiger Zeit habe ich Euch gefragt, wie man am besten ermittelt, wie
lange ein Programm fuer eine Berechnung braucht.

jerry@uni-paderborn.de (Gerald Siek) schrieb mir folgenden Artikel :

---------------------------------------------
>aschmidt@m.isar.de schrieb eines Tages :
>
>Aber jetzt hast Du mich neugierig gemacht : was bewirken InsTime,
>PrimeTime, RmvTime ?

Damit steuert man die Uhr des TimeManager - die kann wahlweise auf
eine Millisekunde oder eine Mikrosekunde genau messen.  Eine Anwendung
sind sog. Alarms, d.h. man kann quasi Interrupts definieren, die nach
einer vorgegebenen Zeit ausgeloest werden (aehnlich den Watchdogs bei
UNIX).   Ausserdem kann man damit die Zeit genauer messen (eben auf
ms oder mys)

Ein einfaches Beispiel (am besten, Du druckst die Mail aus):


// Assumes inclusion of <MacHeaders>

#include <stdio.h>
#include <Timer.h>

void InstallTMTask (void);                      // Prototypen
void ToolBoxInit (void);
void Call_Routine_To_Be_Measured(void);         // Deine Routine


#define kMaxTime   2000          // ##### Max. Ausfuehrungszeit in ms (1)
#####

typedef struct {                // Time Manager information record
        TMTask  atmTask;        // original and revised TMtask record
        long    tmRefCon;       // space to pass address of A5 world (68k
only)
} TMInfo;

typedef TMInfo *TMInfoPtr;      // Pointer to TMInfo struct

TMInfo  myTMInfo;               // our (global) TM information record



void InstallTMTask (void)
{
        // Initialize timer record
        myTMInfo.atmTask.tmAddr = NULL;           // no interrupt - just
measure time (2)
        myTMInfo.atmTask.tmWakeUp = 0;            // initialize tmWakeUp
        myTMInfo.atmTask.tmReserved = 0;          // initialize tmReserved
        myTMInfo.tmRefCon = SetCurrentA5();       // store address of your
A5 world

        InsTime( (QElemPtr) &myTMInfo );          // install the info
record (3)

        PrimeTime( (QElemPtr) &myTMInfo, kMaxTime ); // start ticking timer
(4)
}

void ToolBoxInit ()
{
 // einige Initialisierunsroutinen... 
}

main ()
{
        ToolBoxInit();
        InstallTMTask ();                       

        Call_Routine_To_Be_Measured();

        RmvTime( (QElemPtr) &myTMInfo );                        // (5)
        milliseconds = kMaxTime - myTMInfo.atmTask.tmCount;     // (6)
}



Ein paar Erlaeuterungen:

In (1) legst Du fest, wie lange die zu messende Routine maximal laeuft.
Hier werden 2000ms, also 2sec genommen, Du kannst natuerlich auch z.B.
3600000ms, also 1h nehmen.   Wichtig: Ist die Zahl in (1) *positiv*, so
wird in ms gemessen.  Ist sie negativ, so laeuft der Timer in
Mikrosekunden,
ein Wert von -500 bedeutet also 500 mys, also 1/2000sec.

In (2) legt man fest, welche Routine aufgerufen werden soll, wenn der
Timer abgelaufen ist.  Hier wird NULL eingetragen, also keine Routine. 
Wenn
man bei Ablauf eine Interruptroutine aufrufen will (etwa: "Rechnung zu
lange,
breche ab") muss man noch ein paar Klimmzuege machen - das Installieren
dieser Routine ist nicht ganz trivial.

In (3) wird diese zuvor festgelegte Timerinformation dem TimeManager mit-
geteilt - die Uhr aber nicht gestartet.  Auf diese Weise kann man auch
mehrere Timer abwechselnd oder gleichzeitig laufen lassen.  All diese
Timer werden durch InsTime() in die sog. Time Manager Queue eingetragen.

In (4) wird nun der zuvor eingetragene Timer gestartet und zwar mit der
in (1) definierten Alarmzeit.

Nachden Deine zu messende Routine lief, wird in (5) der Timer aus der
Timer Queue entfernt.  Zu diesem Zeitpunkt, enthaelt das Feld tmCount
die noch verbliebenen Millisekunden bis zum Ablauf, d.h. die Differenz
zwischen Startwert und Restwert ist die verstrichene Zeit.  Dies wird in
(7) berechnet.  *Wichtig*:  Wurde der Timer mit Mikrosekunden, also einer
negativen Zahl geladen, so ist zu diesem Zeitpunkt tmCount ebenfalls
negativ und die verstrichene Zeit ist der Absolutwert der Differenz.
Wurde die Alarmzeit ueberschritten, so ist tmCount stets 0.


Das ganze sieht kompliziert aus - ist aber in dieser Form recht simpel.
Etwas umstaendlicher wird es erst, wenn man in (2) eine Interrupt-
routine installieren will, da *muss* man beim 68k Mac ein ganz klein
bisschen mit Assembler tricksen.  Beim PowerMac geht es relativ
problemlos.

---------------------------------------------

Nun, als ich diese Frage stellte, wusste ich noch nicht, welche
Programmiersprache ich verwenden wuerde. Nachdem bereits ein grosser Teil
auf Pascal vorhanden war, verwendete ich diese Programmiersprache.

Ich schrieb das (Probe-)Programm folgendermaßen um :

--------------- Pascal-Programm Beginn ----------------
program zeitmessung (input,output);

uses timer;

type TMInfo = record atmTask : TMTask;
                  tmRefCon : integer;
              end;
     TMInfoPtr = ^TMInfo;
                  
var a,i, milliseconds : integer;
    myTMInfo : TMInfo;
    
begin

myTMInfo.atmTask.tmAddr := nil;
myTMInfo.atmTask.tmWakeUp := 0;
myTMInfo.atmTask.tmReserved := 0;
myTMInfo.tmRefCon := SetCurrentA5( );

InsTime ( @myTMInfo ); 

PrimeTime ( @myTMInfo, 3600000 );

for i:=1 to 100000 do a := a + 0;   {Nutzzlose Routine zur Zeitberechnung}

RmvTime ( @myTMInfo);

milliseconds := 3600000 - myTMInfo.atmTask.tmCount;
writeln('Zeit : ', milliseconds);    {Ausgabe der verbratenen Zeit}

end.

------------ Pascal Programm Ende ----------------


Das Programm wird zwar fehlerfrei uebersetzt, jedoch die Werte
unterscheiden sich gravierend (mit c++ 'uebersetzt' benoetigt ca 12500
Millisekunden, mit pascal 'uebersetzt' 1 Millisekunde ...) 

Wer kann mir weiterhelfen ? Mein Problem liegt einfach darin, die C++
Befehle

InsTime( (QElemPtr) &myTMInfo );   
PrimeTime( (QElemPtr) &myTMInfo, kMaxTime );
RmvTime( (QElemPtr) &myTMInfo ); 

adaequat ins Pascal zu uebersetzen. InsTime(myTMInfo) etc schlaegt beim
Compilieren fehl ...

Vielen Dank fuer Euere Antworten.


PS: Ich habe alles so ausfuehrlich gelassen ... vielleicht kann ein anderer
diese Routinen benötigen ...



Gruesse aus Muenchen



Alexander Schmidt


-------------------------------------------------------------
Alexander Schmidt                 e-mail : aschmidt@m.isar.de
Lindenstrasse 1, 82031 Gruenwald, Tel/Fax : ++49-89-641 21 82

-------------------------------------------------------------
Technical Details
Message-ID: <AD17673396685C14@aschmidt.m.isar.de>
Path: arc1-ca.pugleaf.net!isar.de!user
References: <ACF1268696684424@aschmidt.m.isar.de>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!isar.de!user
From: aschmidt@m.isar.de (Alexander E. Schmidt)
Newsgroups: de.comp.lang.pascal,de.comp.sys.apple,fido.ger.pascal,zer.z-netz.sprachen.pascal,de.comp.lang.c++
Subject: Zeitvariable II - C++ und Pascal
Date: Tue, 09 Jan 1996 00:28:35 +0200
Organization: I.S.A.R Netzwerke GmbH
Message-ID: <AD17673396685C14@aschmidt.m.isar.de>
References: <ACF1268696684424@aschmidt.m.isar.de>
NNTP-Posting-Host: aschmidt.m.isar.de
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit