2013-07-21 12 views
6

Sono destinato a Windows XP e ho bisogno di una funzione simile a GetTickCount64, che non abbia overflow.Implementazione GetTickCount64 thread-safe per Windows XP

Non riesco a trovare una soluzione decente che sia corretta e thread-safe, così ho provato a rollare il mio.

Ecco cosa mi è venuta:

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; 
} 

E 'davvero thread-safe?

La sicurezza del filo è difficile da controllare per la correttezza, quindi non sono sicuro che sia veramente corretto in tutti i casi.

+4

No, che non è thread-safe. –

+1

Non è nemmeno corretto. La tua chiamata a "InterlockedIncrement" è un'ipotesi al meglio. Sembra anche che tu stia usando "volatile" per significare qualcosa di diverso da quello che fa: [volatile vs. volatile] (http://www.drdobbs.com/parallel/volatile-vs-volatile/212701484). – IInspectable

+0

Grazie per i vostri commenti. Credo di non aver ancora imparato una cosa o due sulla programmazione senza blocco. Beh, ho provato :) In effetti, ho risolto il mio problema in un altro modo ... Non facendo nulla :) Sembra che quando si calcola la differenza tra due risultati GetTickCount, 49 giorni di overflow non rovini i risultati (a meno che la differenza di orario sia così grande). http://stackoverflow.com/a/3692425/2604492 – Paul

risposta

4

Su Windows il problema del timer overflow di solito risolto (nei giochi) con l'utilizzo di QueryPerformanceCounter() funzioni invece di GetTickCount():

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

Poi si può moltiplicare questo numero per il numero reciproco di cicli al secondo per convertire i cicli di secondi :

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

Dopo l'inizializzazione, questo codice è thread-safe:

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

Potete anche checkout il codice sorgente completo (portatile tra Windows e molte altre piattaforme) dal nostro open-source Linderdaum Motore: http://www.linderdaum.com

+0

Grazie per la risposta. Risponde perfettamente alla mia domanda, quindi la contrassegno come accettata, sebbene abbia trovato un'altra soluzione: poiché calcolo solo le differenze di orario, risulta che lo straripamento di 49 giorni non è un problema. http://stackoverflow.com/a/3692425/2604492 – Paul

+2

La risoluzione di '' QueryPerformanceCounter() '' è molto più alta rispetto a '' GetTickCount() '', fino a nanosecondi. –

Problemi correlati