Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / General Programming / General Question for win32 main loop Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
bueyuekt

February 21, 2005, 04:46 AM

I have a question about the main loop.
I see 2 possible versions of getting the messages from
the queue and i am not sure what advantages or disadvantages
each method has...anyone could give some opinions or Infos...

Method 1:

  1.  
  2. while(g_bRun)
  3. {
  4.   while(PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
  5.   {
  6.     TranslateMessage(&msg);    
  7.     DispatchMessage(&msg);
  8.   }
  9. }
  10.  


Method 2:
  1.  
  2. while(g_bRun)
  3. {
  4.   if(PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
  5.   {
  6.     TranslateMessage(&msg);    
  7.     DispatchMessage(&msg);
  8.   }
  9. }
  10.  

 
Victor Widell

February 21, 2005, 05:11 AM

You should use method 1, since there might be severeal events qued up in the same frame. If you just process the first event in each frame, your app might feel sluggish in some scenarios, especially in lower framerates.

 
doorman

February 21, 2005, 07:04 AM

That loop is not being processed once per frame. There is no difference between them. Unless you are going to add extra code to the outer while loop. I wouldn't be surprised if they both compile down to the same assembly code.

 
bueyuekt

February 21, 2005, 07:24 AM

sorry...wrong place posted

 
bueyuekt

February 21, 2005, 07:25 AM

Sorry if it was not clear....

after the PeekMeassage if/while would surely come
code that has to be perform....

In worst event, wouldn't the while(PeekMessage()) statement,
block the main loop??? I mean, if there woould be endless
messages in the queue, then it would do the PeekMessage
endless...or am i wrong?!?

 
Chris

February 21, 2005, 08:33 AM

> I wouldn't be surprised if they both compile down to the same assembly code.

No, he's going to add code inside the first but ouside the second loop.

  1.  
  2. while(g_bRun)
  3. {
  4.   if/while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
  5.   {
  6.     TranslateMessage(&msg);    
  7.     DispatchMessage(&msg);
  8.   }
  9.  
  10.   // game code here
  11. }
  12.  


I'd recommend using "while" over "if". The message queue is finite, so the loop will terminate. If you were using "if", you'd process exactly one message per outer loop iteration (frame?), and the queue could grow larger and larger. It's better to empty it. Usually there won't be many messages anyway (WM_MOUSEMOVE, WM_CHAR, not much else).

In addition, using "if" may slow down resposiveness. Imagine WM_QUIT being put into the queue after 30 WM_MOUSEMOVE messages. Your game would quit only 30 frames later, which might be as much as a second.

 
Cat

February 21, 2005, 01:40 PM

As bueyuekt mentioned above, does the message queue ever grow large enough to noticeably drop frames?

 
hunguptodry

February 21, 2005, 01:46 PM

I think the difference is how often the g_bRun flag is checked. I presume this is volatile and set in DispatchMessage.

If u have a stream of messages that set and unset g_bRun then the "while" version may well miss a transition or two.


 
Dr. Necessiter

February 21, 2005, 04:09 PM

FWIW, here is my main loop:

  1.     // Process all windows messages first.  If no message is waiting, run one
  2.     // frame of the application.  If application is "inactive", call GetMessage()
  3.     // to release control to the windows scheduler.
  4.     PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
  5.     while (msg.message != WM_QUIT)
  6.         {
  7.         if (active)
  8.             gotMsg = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
  9.         else
  10.             gotMsg = GetMessage(&msg, NULL, 0U, 0U);
  11.  
  12.         if (gotMsg)
  13.             {
  14.             TranslateMessage(&msg);
  15.             DispatchMessage (&msg);
  16.             }
  17.         else
  18.             {
  19.             // run one frame of the application
  20.             if (active && ready)
  21.                 {
  22.                 done = DoFrame();
  23.                 // if application signals done, start the shutdown procedure
  24.                 if (done)
  25.                     DestroyWindow(hWnd);
  26.                 }
  27.             }
  28.         }

It is complicated by the fact that I want to be able to release more control to windows when I go into an "inactive" state. That is, I wait on GetMessage() until I am reactivated. I'd love comments, etc. on this. There are a bunch of different ways to handle this and it's nice to find a robust but simple solution.

 
Reedbeta

February 21, 2005, 08:19 PM

The one I use looks like this:

  1. while (true)
  2. {
  3.         // Check for and process any messages
  4.         while (PeekMessage(&msg, NULL, 0, 0, true))
  5.         {
  6.                 TranslateMessage(&msg);
  7.                 DispatchMessage(&msg);
  8.         }
  9.  
  10.         // End on WM_QUIT
  11.         if (msg.message == WM_QUIT)
  12.                 break;
  13.  
  14.         // If renderer is active, render a new frame
  15.         if (active)
  16.         {
  17.                 // Calculate time it took to draw last frame
  18.                 float current_time = GetTime();
  19.                 float frametime = current_time - last_frame_time;
  20.                 last_frame_time = current_time;
  21.  
  22.                 // Clamp frametime to a minimum - occasionally we get a frametime of zero, and this
  23.                 // can cause jerkiness problems (and stability issues in physics simulators)
  24.                 if (frametime < 0.001f) frametime = 0.001f;                             // 1000fps - should be plenty
  25.  
  26.                 // Handle input, logic, update physics, whatnot
  27.                 DoLogic(frametime);
  28.  
  29.                 // Render the scene
  30.                 Render();
  31.         }
  32. }


I know the frametime measurement code isn't the most sophisticated, but it works reasonably well for my purposes =)

 
doorman

February 21, 2005, 09:07 PM

Yep, should have guessed on a game programming site that you would be doing that.

For my 2 cents you want to process all events before rendering the current frame.

The whole purpose of putting your per frame code in that outer loop is to ensure that all spare time is being spent rendering frames. If you have more events than you can process, or spend so long processing those events, then you are saying that there is no spare time for rendering, hence you've got a problem. And changing from a while to an if isnt going to help that.

Process all events as soon as possible after the user has generated them.

 
doorman

February 21, 2005, 09:12 PM

quoting self

> Unless you are going to add extra code to the outer while loop

tool

 
bueyuekt

February 22, 2005, 02:46 AM


@Reedbeta
I think you should get the check for WM_QUIT in your
while(PeekMessage()) loop....cause it could be, that you
have a WM_QUIT Message and after it an Mouse Message,
so the WM_QUIT, could be lost....

 
bueyuekt

February 22, 2005, 02:49 AM

I like the idea... nice code....

Thx....

 
bueyuekt

February 22, 2005, 02:54 AM

I understand what you mean....I am feeling, that
it would be better to process all events first, too...

The rendering could be done as Thread....so there would
be no waitings for Message handling....

Does anyone have experience or info on that???

 
Reedbeta

February 22, 2005, 03:01 AM

Nope, it's guaranteed that there are no more messages after WM_QUIT.

 
Reedbeta

February 22, 2005, 03:03 AM

I'd recommend you don't try to use multithreading. Multithreading won't gain you any advantages, it won't make anything run faster by having the message handling and rendering in separate threads, and it will just create a huge synchronization nightmare. Trust me, the message handling really does not take that much time! =)

 
bueyuekt

February 22, 2005, 03:04 AM

Yes...I read now in MSDN....

thx

 
doorman

February 22, 2005, 03:41 AM

Exactly, almost everyone out there has a single processor unit. You could create a multithreaded program, but you wouldn't see any benefits until someone with a multiprocessor machine ran it. ( Don't know what an effect hyperthreading would have in this case ).

bueyuekt: At this point I recommend you stop asking questions and start doing some testing yourself. Not having a go at you, but you'll learn a lot more with a few simple tests than from getting 1000 peoples opinion on the subject. For example, find out exactly how long your message queue gets between frames. You might be surprised, I would be surprised if it got above 3 or 4. Depends on many things though.

And to tell the truth, I'd really like to know if separating the rendering code into its own thread will create a measurable performance increase on a hyperthreading machine.

 
Steven Don

February 23, 2005, 09:06 AM

Another minor thing: don't filter your messages to just hWnd. If you do, you may get some strange behaviour because other windows in your app don't get their messages. They may be windows you haven't created, even invisible ones, but they're still necessary.

In short, use "NULL" for the second parameter to PeekMessage as several of the above posters already do.

 
This thread contains 20 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.