2013-07-21 19 views
6

Jestem ukierunkowana na system Windows XP i potrzebuję funkcji podobnej do funkcji GetTickCount64, która nie przepełnia.Bezpieczna dla wątków implementacja GetTickCount64 dla systemu Windows XP

Nie mogłem znaleźć przyzwoitego rozwiązania, które jest poprawne i bezpieczne dla wątków, więc spróbowałem wykonać własne.

Oto co wymyśliłem:

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

Czy naprawdę wątku bezpieczne?

Bezpieczeństwo gwintów jest trudne do sprawdzenia pod względem poprawności, więc nie jestem pewien, czy jest to poprawne we wszystkich przypadkach.

+4

Nie, to nie jest bezpieczny wątku. –

+1

To nawet nie jest poprawne. Twoje wezwanie do "InterlockedIncrement" jest w najlepszym wypadku zgadywaniem. Wydaje się również, że używasz 'volatile' do oznaczania czegoś innego niż to: [volatile vs. volatile] (http://www.drdobbs.com/parallel/volatile-vs- volatile/212701484). – IInspectable

+0

Dzięki za komentarze. Sądzę, że muszę jeszcze nauczyć się kilku rzeczy o programowaniu bez blokady. No cóż, próbowałem :) Naprawiłem mój problem w inny sposób ... Nie robiąc nic :) Wydaje się, że przy obliczaniu różnicy między dwoma wynikami GetTickCount, 49-dniowe przepełnienie naprawdę nie psuje wyników (chyba że różnica czasu jest tak duża). http://stackoverflow.com/a/3692425/2604492 – Paul

Odpowiedz

4

W Windows problem przepełnienia timera w zazwyczaj rozwiązane (w grach) z użyciem QueryPerformanceCounter() funkcje zamiast GetTickCount():

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

Następnie można pomnożyć tę liczbę przez liczbę wzajemnego cykli na sekundę do konwersji cykli na sekundy :

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

Po inicjalizacji, ten kod jest wątek bezpieczne:

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

Można również kasy pełny kod źródłowy (Portable pomiędzy Windows i wielu innych platformach) z naszej open source Linderdaum Silnik: http://www.linderdaum.com

+0

Dziękuję za odpowiedź. Doskonale odpowiada na moje pytanie, więc zaznaczam je jako zaakceptowane, chociaż znalazłem inne rozwiązanie: ponieważ obliczam tylko różnice czasowe, okazuje się, że 49-dniowe przepełnienie nie jest problemem. http://stackoverflow.com/a/3692425/2604492 – Paul

+2

Rozdzielczość '' QueryPerformanceCounter() '' jest znacznie wyższa w porównaniu do '' GetTickCount() '', aż do nanosekund. –

Powiązane problemy