QueryPerformanceCounter und überläufe

Ich bin mit QueryPerformanceCounter, um einige timing in meiner Anwendung. Jedoch, nach dem ausführen es für ein paar Tage die Anwendung scheint nicht mehr korrekt funktioniert. Wenn ich einfach die Anwendung neu starten, es beginnt wieder zu arbeiten. Dies macht mich glauben, ich habe eine overflow-problem in meinem timing-code.

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

Meine Frage ist, ob der obige code sollte funktionieren deterministisch für Wochen im Dauerbetrieb laufen?

Ist und wenn nicht wo das problem ist? Ich dachte, der überlauf wurde bearbeitet von

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

Aber vielleicht ist das nicht genug?

EDIT: Bitte beachten, dass ich nicht schreiben der original-code, Ryan M. Geiss, habe den link auf die ursprüngliche Quelle der code ist in der code.

  • static_cast<int>((freq_.QuadPart*2)/1000)) - dies wird schneiden Ihnen alles, was darüber hinaus 32-bit. Sie würde eher erweitern ticks_left zu 64 bits.
  • Denkst du das ist ein problem, obwohl? Sollte nicht QueryPerformanceFrequency immer passen in einen 32-bit integer?
  • Keine Ahnung, ich finde einfach diesen code möglicherweise falsch.
  • Wann, glauben Sie, ticks_left wäre größer als 32 bit?
  • Ja, das sollte wohl geändert werden. Ich versuche nur, um herauszufinden, mit einiger Sicherheit, ob es das problem verursachen könnte oder nicht. So dauert es ~1 Woche zu testen, um es zu überprüfen.
  • Warum würden Sie wollen, führen Sie eine (teilweise) busy-wait wie diese?
  • Zu Verbesserung der Genauigkeit der warten.
  • Warum aber warten überhaupt?
  • Da eine der Anforderungen meiner Anwendung ist, dass es braucht, um "tick" (ausführen einer bestimmten Funktion) in genauen Abständen. Dies ist aufgrund der Abhängigkeit von einer Drittanbieter-Komponente.
  • Das problem mit ticks_left 32 bit ist nicht so, dass die Anzahl der Zecken können zu groß, um fit in den 32 bit, das problem ist die Rechte Seite des Vergleichs zwingt eine 64-bit-Wert in 32 bits, und dies kann die Rendite einen negativen Wert ein, und klicken Sie Vergleich bewertet werden, falsch.

InformationsquelleAutor ronag | 2011-03-14
Schreibe einen Kommentar