Sign in to follow this  

win32: message-loop q.

This topic is 4713 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

checking messages in a win32 program is usually implemented something like this:
while (TRUE)
{
    if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
            break ;
               
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
    }
    else
        Draw(hwnd) ;
}
What I was wondering about .... what if there was SO MANY messages sendt to the program ... then you could in theory not very often end up in the "else" part of the code. or am I totaly silly here? a small q. about win32. Is win32 disapearing? what will take it's place?

Share this post


Link to post
Share on other sites
Use this instead (while loop Peek..)


// Check if a message is in queue
while(1)
{
while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
// check for quit
if(WM_QUIT == msg.message)
m_shutting_down = true;

// Otherwise translate and return control.
TranslateMessage(&msg); // Translate keyboard messages.
DispatchMessage(&msg); // Return control to windows.
}

Draw();
}



[Edited by - LessBread on January 16, 2005 3:11:01 PM]

Share this post


Link to post
Share on other sites
To answer the question about the loop receiving so many messages that it never gets to the 'else' portion. That scenario isn't realistic. You'l find that the loop spends far more time in the 'else' portion than it does dispatching messages.

Your question about the future prospects of Win32 isn't a small one. Is it disappearing? I think Microsoft would like it to disappear so they could start over from scratch.

Share this post


Link to post
Share on other sites
thx for the corrections, I'll correct at once...

I should maybe start another thread about the future of win32 ... but are there any good replacements (as in game development and other resource intencive applications).

Share this post


Link to post
Share on other sites
both of the above are wrong ... the original code you posted suffers from the major flaw that it renders 1 scene per message which would cause your program to do WAY too much work between each message handled ...

but the code they recommend suffers from the opposite flaw, your draw can and will be stalled indefinately when the message queue backs up. This WILL happen. It is not the normal case, and if you choose reasonale timings for the system you are running on it should not happen for large spans of time ... but it will happen any time you are asking the system to do more work than it can actually acomplish ...

On modern computers it is often less of a problem than it used to be, but I wrote a DirectX 6 video slot machine game which ran on an intel 810 board with Windows 98 and it was very much an issue. If we ever configured the timers and rates to exceed the capabilities of the machine, it would begin a spiral of doom that eventually locked the machine up completely.

We had to solve it smarter than that.

The trick is to follow their suggestion of looping over multiple messages while you have them ... but to also peek at either a counter which tells you how many you have processed without drawing, or a timer check to tell you how much time has elapsed since you drew last. The former is quicker and easier, but not very consistent - the latter has higher overhead but gives great consistency.

Here's psudeocode (I don't have the code readily available anymore):


while(!programCompleted)
{
if(msgCount <= MAX_CONTIGOUS_MSGS && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
msgCount = 0;
Draw(hWnd);
}
}


Share this post


Link to post
Share on other sites
Actually, a typical, non-game Win32 program doesn't have an else clause at all. This is the usual way to implement the message loop in a Win32 program:

while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(msg);
DispatchMessage(msg);
}


Unless you actually need a real time loop (although games typically do need one), the above is vastly superior to the PeekMessage() type loop because GetMessage() essentially causes the program to Sleep() until there is a message in the message queue. PeekMessage() is bad for most applications because using it the way it is typically used causes your program to automatically use up all available processor cycles, even when it isn't really doing anything. Just imagine if Internet Explorer had 99% processor usage!

Share this post


Link to post
Share on other sites
if windows had decent sleep / scheduler characteristics (like BeOS did) then even games have no reason to use 100% cpu. On BeOS the scheduler had 1 ms accuracy so in theory even about 500 frames a second could be acheived while using sleep, on Windows 9x series the scheduler doesn't guarantee it can awake from sleeping in less than 55 ms ... even when computer is idle - so you are limited to 18.2 frames / sec using that system. I think NT/200/XP have better characteristics, but most games still need to support 98 for a while longer, so you can't really use sleep in a game.

The REAL system we used on our 98 game was to have an else clause who's primary job was to PostMessages from our high performance timer system (windows normal timers are likelwise limited to 18.2 Hz, while our HP timer system game us fairly accurate posts exceeding 100Hz (depending on CPU and load it varied from about 60-200 Hz before degrading).

Share this post


Link to post
Share on other sites
Quote:
Original post by LessBread
To answer the question about the loop receiving so many messages that it never gets to the 'else' portion. That scenario isn't realistic. You'l find that the loop spends far more time in the 'else' portion than it does dispatching messages.

Your question about the future prospects of Win32 isn't a small one. Is it disappearing? I think Microsoft would like it to disappear so they could start over from scratch.


Agreed! I once thought about that scenario and I could never get it to happen on my comp (P4 3.2 HT) If it were possible - then in peter_b's example - it would never reach the draw - so the loop would be screwed either way. As for the Win32 question, I do not know, but maybe there was a reason why Managed Code was developed [wink].

Share this post


Link to post
Share on other sites
Quote:
Original post by Xai
but the code they recommend suffers from the opposite flaw, your draw can and will be stalled indefinately when the message queue backs up. This WILL happen.


I have a hard time beliving that this scenario can happen. You mean that windows will start generationg so many messages for your window that the while(Peek) will never end? Surley you see that if that were to happen something exeptional have happend and any program would be doomed to fail in a matter of time. Your approach to solve it wouldnt work any better if that were to happen, granted you would handle a few messages every frame, but since windows now is generating enough messages to "stall indefinately", the message queue would continue to grow, and grow out of bound pretty fast, even if you handle a limited number of messages every frame.

The only way you could get this to happen is probebly if you are posting messages to your own window in your winproc.

Share this post


Link to post
Share on other sites
The window messages can indeed go on forever. Click the titlebar of the window, and don't release it, and you'll see what I mean.

Share this post


Link to post
Share on other sites
unless you put the "game program" in its own thread, you will always depend on the messageloop somewhat...

I see it is good to limit the que to deal with just a certain amount of messages .... but I fear the danger of the messages queing up too much and become a problem...

Share this post


Link to post
Share on other sites
Quote:
Original post by Nemesis2k2
What does everyone else think about placing the message loop into a seperate thread?
Only the thread that created the window can check it's messages, so your program would fail if you put only the message loop in a different thread. If you have two threads (one for messages and one for game), then the message thread must also create the window. Also, the game loop still needs to check messages because there are those mythical 'thread messages' that aren't too a window.

Personally, I make a 'bool ProcessMessages()' function that checks a certain number of message (using a for loop and breaking when no messages remain) that returns true as long as the message is not a quit message. Then I can do While(ProcessMessages()){...}

Share this post


Link to post
Share on other sites
Quote:
Original post by Xai
both of the above are wrong ... the original code you posted suffers from the major flaw that it renders 1 scene per message which would cause your program to do WAY too much work between each message handled ...

but the code they recommend suffers from the opposite flaw, your draw can and will be stalled indefinately when the message queue backs up.


Take a closer look at both methods. They are functionally identical. Both will only call Draw when there are no messages to process.

Share this post


Link to post
Share on other sites
you are right, they both do that ... I misread the original one ...

as for the post by peter_b about the thread being doomed anyway ... you are right if a storm of messages comes and keeps coming, your program will crash no matter what you do. In fact, my recommendations would speed up that eventual demise, because the draw takes time away from message handling. But the purpose of the system is not to handle the system of messages being generated faster than they are processed forever (a flood that goes on forever cannot be survived).

The real life situation is surviving floods that last only a short while, in the best possible way.

The question is how to smooth out the bumps that occur is a short lived flury of messages occurs. The answer is to not let the contents of the message queue starve your critical path. Now what your critical path is is up to you, sometimes drawing should wait, so you can handle networking, or catch up on game logic, or whatever. The key is that you, the designer should choose what aspect of your program has a higher priority than the rest, and ensure that it gets a reasonable minimum time slice (as much as possible).

Share this post


Link to post
Share on other sites

This topic is 4713 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this