Article View: de.comp.lang.pascal
Article #28Zeitvariable II - C++ und Pascal
From: Alexander E. Schmidt
Date: Mon, 08 Jan 1996 22:58
Date: Mon, 08 Jan 1996 22:58
202 lines
7074 bytes
7074 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:
<AD176E2696681FE55@aschmidt.m.isar.de>Path:
arc1-ca.pugleaf.net!isar.de!userReferences:
<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:58:14 +0200 Organization: I.S.A.R Netzwerke GmbH Message-ID: <AD176E2696681FE55@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