|
Die nachfolgend vorgestellte Klasse CElapsed bietet eine Lösung des Problems auf Basis der Win32 API-Funktionen QueryPerformanceFrequency() und QueryPerformanceCounter(). Diese beiden Funktionen sind in WINBASE.H wie folgt deklariert:
BOOL QueryPerformanceCounter(
LARGE_INTEGER *lpPerformanceCount);
BOOL QueryPerformanceFrequency(
LARGE_INTEGER *lpFrequency);
Die Funktion QueryPerformanceCounter() liefert im Parameter lpPerformanceCounter die Anzahl der Ticks, die mit der durch QueryPerformanceFrequency() in lpFrequency gelieferten Frequenz multipliziert werden muß, um die tatsächlich vergangene Zeit zu ermitteln.
Der als Frequenz gelieferte Wert stimmt mit der Clock Frequenz der PII- und PPro-CPU überein, der Counter entspricht einem Zähler der CPU Clock Ticks. Dies führt zusammen zu einer extrem hohen Auflösung der Zeitmessung, bringt jedoch den Nachteil mit sich, daß zum einen die Funktionalität nicht von jeder CPU bereitgestellt wird, zum anderen besitzen verschiedene CPUs unterschiedliche Frequenzen, so daß die Frequenzwerte und die Ticks nicht direkt miteinander vergleichbar sind, sondern nur die realen Sekunden, die dem Produkt der beiden Werte entsprechen.
Die Klasse CElapsed ist somit letztlich ein Wrapper um diese beiden Funktionen und bietet ein wenig mehr Komfort als die beiden rudimentären API-Funktionen.
Der Datentyp LARGE_INTEGER, wird intern als __int64 abgebildet und nimmt die Frequenz wie auch die Startzeit auf.
class CElapsed
{
private :
__int64 Frequency;
__int64 BeginTime;
int Initialized;
Das Ermitteln des Frequenzwerts erfolgt im Konstruktor, der auch gleich im Member Initialized festhält, ob eine Frequenz ermittelt wurde und die Methoden der Klasse eingesetzt werden dürfen.
public :
CElapsed()
{
Initialized = QueryPerformanceFrequency(
(LARGE_INTEGER *) &Frequency);
}
Der Start der Zeitmessung erfolgt über die Methode Begin(), die zunächst die Zulässigkeit des Aufrufs überprüft und dann den aktuellen Stand des Counters.
BOOL Begin()
{
if (!Initialized)
return 0;
return QueryPerformanceCounter((LARGE_INTEGER *)&BeginTime);
}
Analog dazu ermittelt die Methode End() den Stand des Counters und returniert die Differenz zwischen End- und Startzeitpunkt als Sekundenwert, der sich aus der Division der verstrichenen Ticks in elapsed durch Frequency ergibt:
double End()
{
if( ! Initialized )
return 0.0;
__int64 endtime;
QueryPerformanceCounter((LARGE_INTEGER *)&endtime );
__int64 elapsed = endtime - BeginTime;
return (double)elapsed / (double)Frequency;
}
Die Methode Available() gibt Auskunft darüber, ob die Zeitmessung verfügbar ist (TRUE) oder nicht (FALSE), wobei letzteres nur dann möglich ist, wenn der Aufruf von QueryPerformanceFrequency() fehlgeschlagen ist.
|