Win32: HiResTimer class

This simple little C++ class wraps Kernel32's QueryPerformanceCounter API.

Usage is straightforward:

CHiResTimer hrt;

hrt.Start();
DoSomethingLengthy();
hrt.Stop();

printf("%I64u", hrt.GetElapsedMicroseconds());

The hi-res timer API deals in unsigned, 64-bit integer values, so the problem of rollover (or "lapping") is not really an issue -- even on a box with a 1GHz timer frequency, 500 years will pass by before the counter laps its start position.

However, not all systems support the hi-res timer API (pre-Pentium II? non-Intel?).  The IsSupported method can be used to determine this, at run-time.

Finally, because it can be somewhat awkward to comment-out all of the references to CHiResTimer (4 non-contiguous lines, in the above trivial example!) I've included a handy preprocessor symbol (NOTIMER) to render the class inert.

#pragma once


namespace Util
{
    class CHiResTimer
    {
        // Construction

    public:

        CHiResTimer()
        {
#ifndef NOTIMER
            a = b = 0Ui64;
            ::QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>(&f));
#endif
        }

        // Properties
     
    public:

        bool IsSupported() const
        { return ( ( f == 0) ? false : true); }

        unsigned __int64 GetElapsedTicks() const
#ifndef NOTIMER
        { return (b-a); }
#else
        { return 0Ui64; }
#endif

        unsigned __int64 GetElapsedMicroseconds() const
#ifndef NOTIMER
        {
            unsigned __int64 d = (b-a); 
            if (d < 0x10c6f7a0b5edUi64) // 2^64 / 1e6
                return (d*1000000Ui64)/f; 
            else
                return (d/f)*1000000Ui64;
        }
#else
                { return 0Ui64; }
#endif

        unsigned __int64 GetFrequency() const
#ifndef NOTIMER
        { return f; }
#else
        { return 1Ui64; }
#endif

        // Methods

    public:

        void Start()
        {
#ifndef NOTIMER
            ::Sleep(0);
            ::QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>(&a));
#endif
        }

        unsigned __int64 Stop()
        {
#ifndef NOTIMER
            ::QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>(&b));
            return GetElapsedTicks();
#else
            return 0Ui64;
#endif
        }

        // Implementation

    protected:

#ifndef NOTIMER
            __int64 a, b, f;
#endif
    };
}