Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread-safe GetTickCount64 implementation for Windows XP

Tags:

winapi

I'm targeting Windows XP, and I need a function similar to GetTickCount64, that does not overflow.

I couldn't find a decent solution that is correct and thread safe, so I tried to roll my own.

Here's what I came up with:

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

Is it really thread safe?

Thread safety is difficult to check for correctness, so I'm not sure whether it's really correct in all cases.

like image 307
Paul Avatar asked Jul 21 '13 15:07

Paul


1 Answers

On Windows the timer overflow problem in usually solved (in games) with using QueryPerformanceCounter() functions instead of GetTickCount():

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

Then you can multiply this number by reciprocal number of cycles per second to convert cycles to seconds:

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

After initialization, this code is thread safe:

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

You can also checkout the full source code (portable between Windows and many other platforms) from our open-source Linderdaum Engine: http://www.linderdaum.com

like image 156
Sergey K. Avatar answered Oct 24 '22 16:10

Sergey K.