QueryPerformanceCounter и переполнения

Я использую QueryPerformanceCounter для определения времени в моем приложении. Однако после нескольких дней работы приложение перестает работать должным образом. Если я просто перезапущу приложение, оно снова начнет работать. Это заставляет меня думать, что у меня проблема с переполнением в моем временном коде.

// Author: Ryan M. Geiss
// http://www.geisswerks.com/ryan/FAQS/timing.html
class timer
{
public:
    timer()
    {
        QueryPerformanceFrequency(&freq_);
        QueryPerformanceCounter(&time_);
    }

    void tick(double interval)
    {       
        LARGE_INTEGER t;
        QueryPerformanceCounter(&t);

        if (time_.QuadPart != 0)
        {
            int ticks_to_wait = static_cast<int>(static_cast<double>(freq_.QuadPart) * interval);
            int done = 0;
            do
            {
                QueryPerformanceCounter(&t);

                int ticks_passed = static_cast<int>(static_cast<__int64>(t.QuadPart) - static_cast<__int64>(time_.QuadPart));
                int ticks_left = ticks_to_wait - ticks_passed;

                if (t.QuadPart < time_.QuadPart)    // time wrap
                    done = 1;
                if (ticks_passed >= ticks_to_wait)
                    done = 1;

                if (!done)
                {
                    // if > 0.002s left, do Sleep(1), which will actually sleep some 
                    //   steady amount, probably 1-2 ms,
                    //   and do so in a nice way (cpu meter drops; laptop battery spared).
                    // otherwise, do a few Sleep(0)'s, which just give up the timeslice,
                    //   but don't really save cpu or battery, but do pass a tiny
                    //   amount of time.
                    if (ticks_left > static_cast<int>((freq_.QuadPart*2)/1000))
                        Sleep(1);
                    else                        
                        for (int i = 0; i < 10; ++i) 
                            Sleep(0);  // causes thread to give up its timeslice
                }
            }
            while (!done);            
        }

        time_ = t;
    }       
private:    
    LARGE_INTEGER freq_;
    LARGE_INTEGER time_;
};

Мой вопрос в том, должен ли приведенный выше код работать детерминированно в течение нескольких недель непрерывной работы?

А если не в чем проблема? Я думал, что переполнение было обработано

if (t.QuadPart < time_.QuadPart)    // time wrap
    done = 1;

Но, может быть, этого недостаточно?

РЕДАКТИРОВАТЬ: Обратите внимание, что я не писал исходный код, а Райан М. Гейсс, ссылка на исходный код находится в коде.

5
задан Ellioh 28 November 2013 в 16:38
поделиться