views:

136

answers:

4

After noticing some timing descrepencies with events in my code, I boiled the problem all the way down to my Windows Message Loop.

Basically, unless I'm doing something strange, I'm experiencing this behaviour:-

MSG message;

while (PeekMessage(&message, _applicationWindow.Handle, 0, 0, PM_REMOVE))
{
    int timestamp = timeGetTime();
    bool strange = message.time > timestamp; //strange == true!!!

    TranslateMessage(&message);
    DispatchMessage(&message);
}

The only rational conclusion I can draw is that MSG::time uses a different timing mechanism then timeGetTime() and therefore is free to produce differing results. Is this the case or am i missing something fundemental?

+1  A: 

Could this be a signed unsigned issue? You are comparing a signed int (timestamp) to an unsigned DWORD (msg.time).

Also, the clock wraps every 40ish days - when that happens strange could well be true.

As an aside, if you don't have a great reason to use timeGetTime, you can use GetTickCount here - it saves you bringing in winmm.

The code below shows how you should go about using times - you should never compare the times directly, because clock wrapping messes that up. Instead you should always subtract the start time from the current time and look at the interval.

// This is roughly equivalent code, however strange should never be true
// in this code
DWORD timestamp = GetTickCount();
bool strange = (timestamp - msg.time < 0);
Stewart
"As an aside, if you don't have a great reason to use timeGetTime, you can use GetTickCount here - it saves you bringing in winmm." great tip thanks. I figured GetTickCount would be more leg work to get included!
Adam Naylor
I checked the types as i thought the same thing but the values are all positive and within range.
Adam Naylor
Adam - the code above is still wrong and will fail in unexpected ways when the system clock wraps. The values are obviously all positive, because they are all unsigned by the way.
Stewart
I think the test should be `bool strange = (signed long)(timestamp - msg.time) < 0;` @Stewart, no, that will not fail even if the numbers warp, because then the subtraction will wrap as well.
Fozi
A: 

I don't think it's advisable to expect or rely on any particular relationship between the absolute values of timestamps returned from different sources. For one thing, the multimedia timer may have a different resolution from the system timer. For another, the multimedia timer runs in a separate thread, so you may encounter synchronisation issues. (I don't know if each CPU maintains its own independent tick count.) Furthermore, if you are running any sort of time synchronisation service, it may be making its own adjustments to your local clock and affecting the timestamps you are seeing.

Brian Nixon
A: 

Are you by any chance running an AMD dual core? There is an issue where since each core has a separate timer and can run at different speeds, the timers can diverge from each other. This can manifest itself in negative ping times, for example.

I had similar issues when measuring timeouts in different threads using GetTickCount().

Install this driver (IIRC) to resolve the issue.

Fozi
I've reproduced the OP's issue on my Intel box, so I don't think this is the case.
Matt
A: 

MSG.time is based on GetTickCount(), and timeGetTime() uses the multimedia timer, which is completely independent of GetTickCount(). I would not be surprised to see that one timer has 'ticked' before the other.

Eric Brown