Countdown seems to finish before it should: the client's clock is still running when the server ends the game. I've observed this with two windows xp computers, when I run server and (one) client on the same computer. Taking a closer look, the server's clock is running way too fast from the beginning. To my surprise, I couldn't find any previous posts on this topic. Can others confirm this, and do you have any suggestions for correcting this? It seems to me that both server and client use the same (dreadful) TimeKeeper functions. Thanks for your comments.
Edit: This seems to be related to how fast the server's main loop iterates (waitTime): the longer the delay, the more the clock advances. The real delay between loop iterations is almost exactly two times smaller than the intended value in waitTime! No idea how this should happen. If the main loop is set to run continuously, the timing is almost accurate.
Server timing
Server timing
"There's no such thing as stupid questions. There's just stupid people." - Mr. Garrison
Re: Server timing
Ok, think I managed to solve this. The error occurs when two calls to TimeKeeper::getCurrent() function are made too close to each other.
1. The time difference from last measurement is calculated at the beginning of function GetCurrent():
2. Then there is some strange code related to the recalibration of QPC frequency:
3. Only after this the qpcLastTime gets updated:
The problem is that because the variable qpcLastTime is static, the second call to getCurrent may use the old value before the first call has had time to update it (its probably stuck in the second phase). So, suppose that two calls close to each other are made 3 seconds after a previous one. Because qpcLastTime is not updated properly, both calls now add 3 seconds to the time, making the clock run at double speed.
To fix this, one perhaps needs to use lock for the last phase. Removing the second phase also seems to work in practise.
Hope this would help someone in the future.
1. The time difference from last measurement is calculated at the beginning of function GetCurrent():
Code: Select all
LONGLONG diff = now.QuadPart - qpcLastTime.QuadPart;
Code: Select all
if (clkSpent > qpcFrequency) {
// Recalibrate Frequency
DWORD tgt = timeGetTime();
DWORD deltaTgt = tgt - timeLastCalibration;
timeLastCalibration = tgt;
qpcLastCalibration = now.QuadPart;
if (deltaTgt > 0) {
LONGLONG oldqpcfreq = qpcFrequency;
qpcFrequency = (clkSpent * 1000) / deltaTgt;
if (qpcFrequency != oldqpcfreq)
logDebugMessage(4,"Recalibrated QPC frequency. Old: %f ; New: %f\n",
(double)oldqpcfreq, (double)qpcFrequency);
}
}
Code: Select all
currentTime += (double) diff / (double) qpcFrequency;
qpcLastTime = now;
To fix this, one perhaps needs to use lock for the last phase. Removing the second phase also seems to work in practise.
Hope this would help someone in the future.
"There's no such thing as stupid questions. There's just stupid people." - Mr. Garrison
Re: Server timing
The timekeeper has been re-written significantly in the trunk version of the source code.
JeffM