2013-07-21 13 views
6

Ich bin auf Windows XP ausgerichtet, und ich brauche eine Funktion ähnlich GetTickCount64, die nicht überläuft.Thread-sichere GetTickCount64-Implementierung für Windows XP

Ich konnte keine anständige Lösung finden, die korrekt und Thread-sicher ist, also habe ich versucht, mein eigenes zu rollen.

Hier ist, was ich kam mit:

ULONGLONG MyGetTickCount64(void) 
{ 
    static volatile DWORD dwHigh = 0; 
    static volatile DWORD dwLastLow = 0; 
    DWORD dwTickCount; 

    dwTickCount = GetTickCount(); 
    if(dwTickCount < (DWORD)InterlockedExchange(&dwLastLow, dwTickCount)) 
    { 
     InterlockedIncrement(&dwHigh); 
    } 

    return (ULONGLONG)dwTickCount | (ULONGLONG)dwHigh << 32; 
} 

Ist es wirklich Thread-sicher?

Thread-Sicherheit ist schwierig, um die Richtigkeit zu überprüfen, so dass ich nicht sicher bin, ob es wirklich in allen Fällen richtig ist.

+4

Nein, das ist nicht Thread-sicher. –

+1

Es ist nicht einmal richtig. Ihr Aufruf an "InterlockedIncrement" ist bestenfalls eine Vermutung. Sie scheinen auch "volatile" zu verwenden, um etwas anderes zu meinen als es: [volatile vs. volatile] (http://www.drdobbs.com/parallel/volatile-vs-volatile/212701484). – IInspectable

+0

Danke für Ihre Kommentare. Ich denke, ich muss noch etwas über die Lock-Free-Programmierung lernen. Nun, ich habe versucht :) In der Tat, löste ich mein Problem auf andere Weise ... Durch nichts zu tun :) Es scheint, dass bei der Berechnung der Unterschied zwischen zwei GetTickCount Ergebnisse, 49-Tage-Überlauf nicht wirklich die Ergebnisse vermasseln (außer der Zeitunterschied ist so groß). http://stackoverflow.com/a/3692425/2604492 – Paul

Antwort

4

Unter Windows in dem Timer Überlaufproblem in der Regel (in Spielen) gelöst mit QueryPerformanceCounter() Funktionen statt GetTickCount() mit:

double GetCycles() const 
{ 
    LARGE_INTEGER T1; 
    QueryPerformanceCounter(&T1); 
    return static_cast<double>(T1.QuadPart); 
} 

Dann können Sie diese Zahl durch reziproke Anzahl der Zyklen pro Sekunde multiplizieren Zyklen Sekunden zu konvertieren : Dieser Code

void Initialize() 
{ 
    LARGE_INTEGER Freq; 
    QueryPerformanceFrequency(&Freq); 
    double CyclesPerSecond = static_cast<double>(Freq.QuadPart); 
    RecipCyclesPerSecond = 1.0/CyclesPerSecond; 
} 

Nach der Initialisierung wird threadsicher:

double GetSeconds() const 
{ 
    return GetCycles() * RecipCyclesPerSecond; 
} 

Sie können auch den vollständigen Quellcode (portable zwischen Windows und vielen anderen Plattformen) von unserem Open-Source Linderdaum Motor Kasse: http://www.linderdaum.com

+0

Vielen Dank für Ihre Antwort. Es beantwortet meine Frage perfekt, also markiere ich es als akzeptiert, obwohl ich eine andere Lösung gefunden habe: Da ich nur Zeitunterschiede berechne, stellt sich heraus, dass 49-Tage-Überlauf kein Problem ist. http://StackOverflow.com/a/3692425/2604492 – Paul

+2

Die Auflösung von '' QueryPerformanceCounter() '' ist viel höher im Vergleich zu '' GetTickCount() '', bis zu Nanosekunden. –