سؤال

I am trying to write a class that will be able to time events using QueryPerformanceCounter in C++. The idea is that you create a timer object, give a function a time in double format, and it counts until that time has passed by and does stuff afterwards. This class will ideally be used for timing things in a game ( having a timer that counts 60 times in a second for example). When i compile this code though, it just prints 0's to the console, seemingly for ever. But i noticed some kind of bug that i can't understand. If i click on the scroll bar of the console window and hold it, the timer actually counts properly. If i enter 5.0 for example, then quickly click and hold the scroll bar for 5 seconds or longer, when i let go the program will print 'Done!!!'. so why doesn't it count properly when i just let it print the elapsed time to the console? is there a glitch with printing things to the console, or is there something wrong with my timing code? Below is the code:

   #include <iostream>
#include <iomanip>
#include "windows.h"

using namespace std;



int main()
{

    setprecision(10); // i tried to see if precision in the stream was the problem but i don't think it is

    cout << "hello! lets time something..." << endl;

    bool timing = 0;                // a switch to turn the timer on and off
    LARGE_INTEGER T1, T2;           // the timestamps to count
    LARGE_INTEGER freq;             // the frequency per seccond for measuring the difference between the stamp values

    QueryPerformanceFrequency(&freq); // gets the frequency from the computer

    // mil.QuadPart = freq.QuadPart / 1000; // not used


    double ellapsedtime = 0, desiredtime; // enter a value to count up to in secconds
    // if you entered 4.5 for example, then it should wait for 4.5 secconds

    cout << "enter the amount of time you would like to wait for in seconds (in double format.)!!" << endl;
    cin >> desiredtime;

    QueryPerformanceCounter(&T1);   // gets the first stamp value
    timing = 1;                    // switches the timer on

    while(timing)
    {
        QueryPerformanceCounter(&T2);      // gets another stamp value
        ellapsedtime += (T2.QuadPart - T1.QuadPart) / freq.QuadPart;   // measures the difference between the two stamp
        //values and then divides them by the frequency to get how many secconds has ellapsed
        cout << ellapsedtime << endl;
        T1.QuadPart = T2.QuadPart; // assigns the value of the second stamp to the first one, so that we can measure the
        // difference between them again and again

        if(ellapsedtime>=desiredtime) // checks if the elapsed time is bigger than or equal to the desired time,
        // and if it is prints done and turns the timer off
        {
            cout << "done!!!" << endl;
            timing = 0; // breaks the loop
        }
    }



    return 0;
}
هل كانت مفيدة؟

المحلول

You should store in ellapsedtime the number of microseconds elapsed since the fisrt call to QueryPerformanceCounter, and you should not overwrite the first time stamp.

Working code:

// gets another stamp value
QueryPerformanceCounter(&T2);     

// measures the difference between the two stamp
ellapsedtime += (T2.QuadPart - T1.QuadPart);

cout << "number of tick " << ellapsedtime << endl;
ellapsedtime *= 1000000.;
ellapsedtime /= freq.QuadPart;
cout << "number of Microseconds " << ellapsedtime << endl;

// checks if the elapsed time is bigger than or equal to the desired time
if(ellapsedtime/1000000.>=desiredtime)         {
   cout << "done!!!" << endl;
   timing = 0; // breaks the loop
}

Be sure to read : Acquiring high-resolution time stamps

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top