• Advertisement

Archived

This topic is now archived and is closed to further replies.

removing the message pump

This topic is 6207 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

I remember reading an article on this site about a month ago about removing the message pump from windows programming and just doing the programming like we did back in the DOS days. for example if i want to wait at a certain screen and wait for the user to type in their name or something, I would need some kind of gameState variable that told me in my mainGameFunction to go and run the function that draws that specific image to the screen and accept user input, etc..... I want to just be able to do a loop in that one function that loops until they press enter or something. But I have heard that it is bad to keep windows programs in loops like this. Why is it bad ? Can i just not run the message pump and be OK ? Or can I just start a different thread for the game like the article stated ? "Now go away or I shall taunt you a second time" - Monty Python and the Holy Grail

Share this post


Link to post
Share on other sites
Advertisement
One thing you can do is have a function called "ProcessMessages" which returns false if the user pressed alt-F4 or whatnot. Then you can have functions which take up multiple frames, so long as you have the line "if(!ProcessMessages()) return false;" or something to that effect. That could work nicely, and won''t require multithreaded programming.

Share this post


Link to post
Share on other sites
quote:

I want to just be able to do a loop in that one function that loops until they press enter or something. But I have heard that it is bad to keep windows programs in loops like this. Why is it bad ? Can i just not run the message pump and be OK ? Or can I just start a different thread for the game like the article stated ?



Put simply, yes you can do it but no, you shouldn''t. Cutting off the message loop cuts off everything until you get it back. The exception is Alt-F4, I think. Anyways, it''s bad to do that: pretend you''re making a game like Chrono Trigger for the SNES. In that game, you could often walk around while a textbox is up. This means that it''s in a loop for the textbox (waiting to be closed) but also it''s able to receive user input. If you cut off the Windows message loop, you can''t get input without using DirectInput or GetAsyncKeyState (). I know it''s a bad hypothetical situation but you get the idea.

Anyway, it means you could miss more important messages, such as the keypress for quitting or the click on the close box. If the message loop is suspended, those probably won''t work.

Either use states or threads. Be warned though that threads have their own drawbacks.


-Goku
SANE Productions Homepage

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I don''t know what your all on about. In all of my program''s i cut off the message loop cause im used to programming dos applications. The programs work fine. I have an RTS game up and running, which features music, sound effects, mouse input, keyboard and the program doesn''t miss any keystrokes or clicks.

All ive done is have my whole program in the initialisation of the window. The program doesn''t even touch the windows pump.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I don''t know what your all on about. In all of my program''s i cut off the message loop cause im used to programming dos applications. The programs work fine. I have an RTS game up and running, which features music, sound effects, mouse input, keyboard and the program doesn''t miss any keystrokes or clicks.

All ive done is have my whole program in the initialisation of the window. The program doesn''t even touch the message pump.

So if you don''t want to use the message pump then simply dont.

Share this post


Link to post
Share on other sites
im not using any windows dialogs in my game and dont plan too. I am already using DirectInput anyway.....so why should I not cut off the message pump. There arent going to be any windows messages sent to my window anyway......
and one else have an opinion ?


"Now go away or I shall taunt you a second time"
- Monty Python and the Holy Grail

Share this post


Link to post
Share on other sites
If you read the article a bit deeper you would have seen that what they suggested was to create a second thread. In this second thread you can create your game loop or whatever just like the old days. The main thread is still running a message pump just like any normal Windows application.

You need the message pump to handle such things as task switching, shutdown, power-saving and a broad range of other possibilities. Don''t cause yourself a whole load of heartache by trying to remove it entirely.

To the anonymous poster who claims to have no message loop at all. How friendly does your application interact with other applications on the system? If someone task-switches to another application, does yours go to sleep and recover when it becomes again?

Steve ''Sly'' Williams  Code Monkey  Krome Studios

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster

I don't know what your all on about. In all of my program's i cut off the message loop cause im used to programming dos applications. The programs work fine. I have an RTS game up and running, which features music, sound effects, mouse input, keyboard and the program doesn't miss any keystrokes or clicks.

All ive done is have my whole program in the initialisation of the window. The program doesn't even touch the message pump.

So if you don't want to use the message pump then simply dont.



Actually, I don't think you know what you're talking about. You can't create a program and have it working perfectly and not have a message pump to handle the messages. If you switch the task, your program will crash or cause some illegal operation errors. Unless you use MFC which actually take care of the PUMP for you but then you still have one, it's just hidden in a class member function. Now, unless you know what you're talking about, don't post.

Oh and:

Have a nice day...


Cyberdrek
Headhunter Soft
DLC Multimedia

Edited by - Cyberdrek on February 18, 2001 12:25:49 AM

Share this post


Link to post
Share on other sites
That''s true. The first thread in any Win32 process is given a message pump (yes even a console mode program has one).

Any secondary threads you create do NOT start off with a message pump until you make a UI API call (example PeekMessage()). As soon as you use one of those functions, Windows will automatically attach a message pump for you.

There is no reason for you to cut the Windows message pump out of the loop. You can still achieve DOS style programming by not returning from some game function.

Don''t over complicate a simple problem.

Dire Wolf
direwolf@digitalfiends.com

Share this post


Link to post
Share on other sites
well if i just dont return from a game function, then i wont get back to the part of my program that process messages.
In winmain i have
  
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
// Handle messages

if (!GetMessage(&msg, NULL, 0, 0))
{
return msg.wParam;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// No messages? then run program loop

if (appActive)
{
// Call critical in game.cpp

mainEngineCritical();
}
else
{
// Pause if application is not active

WaitMessage();
}
}

that is how i process the messages
so if i never return out of a game function then i never get back to this point and wont process anymore messages


"Now go away or I shall taunt you a second time"
- Monty Python and the Holy Grail

Share this post


Link to post
Share on other sites
You must still process the message pump in one shape or another. Not doing so is bad in so many ways... Don''t do this.

Share this post


Link to post
Share on other sites
My point about not return from your game function was misunderstood. You only return from your game function occassionally (maybe every 5 seconds or so) to process Windows messages. You''d end up using DirectInput to receive input in your game function (which there should be many of - AI, UI, etc).

Sorry if I confused you.

Dire Wolf
direwolf@digitalfiends.com

Share this post


Link to post
Share on other sites
Then every Windows message that you wanted to handle would be delayed up to 5 seconds. This is unacceptable. You may think you can just ignore the input if you want, but there are screen saver messages, messages to close the app when the user hits Shut Down... from the Start Menu, power-saving messages, display mode messages (for windowed apps this is especially important!), window movement, resizing, etc.

Why bother using Windows if people won''t spend 5 minutes of forethought to make them provide the most basic Windows features?

Share this post


Link to post
Share on other sites
  
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)

{
//...

g_evExit = CreateEvent(0, TRUE, FALSE, 0);

HANDLE thrGame;
thrGame = (HANDLE)_beginthreadex(NULL, 0, GameThread, 0, 0, 0);
SetThreadPriority(thrGame, THREAD_PRIORITY_IDLE);

// Main message loop:

while(GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
SetEvent(g_evExit);
if(WAIT_TIMEOUT==WaitForSingleObject(thrGame, 5000))
TerminateThread(thrGame, -1);
CloseHandle(g_evExit);
return(0);
}

unsigned int __stdcall GameThread(void* voidp)
{
CoInitialize(NULL);
ShowWindowAsync(*g_cwndSplash, SW_SHOW);
//...

while(WAIT_OBJECT_0!=WaitForSingleObject(g_evExit, 0))
{
QueryPerformanceCounter(&liNow_us);
dwTime_ms = liNow_us.LowPart / 1000;
fTime_sec = static_cast<float>(liNow_us.LowPart) / 1000000.0f;
Render(fTime_sec);
//other stuff

}

CoUninitialize();
_endthreadex(0);
return(0);
}


works great

Magmai Kai Holmlor
- The disgruntled & disillusioned

Share this post


Link to post
Share on other sites
But then you need the large return value chains, which are merely a painful way of manually implementing exceptions. The Windows message loop and the game loop are two independent things. Using multiple threads is a simple and easy solution if the threads do not require much synchronization.

Out of the messages I listed, only two require communication between the process and the game thread: WM_DISPLAYCHANGE and WM_ACTIVATE. The rest can be handled completely by the process.

So, what is the proper way to sync the code that handles these two messages?

Obviously, WM_DISPLAYCHANGE occurs only in windowed mode (i.e., nonexclusive mode). If you check for lost surfaces each time you blit, then the only code to be adversely affected by WM_DISPLAYCHANGE is that which directly manipulates surface memory. How and when that code is called determines how you synchronize the message.

WM_ACTIVATE is called when the user presses ALT-TAB or simply changes the focus to another window in windowed mode (i.e., nonexclusive mode). This code doesn''t really affect the game if you''ve got a clipper attached to your window. You can do one of two things with this message: 1) use SuspendThread and ResumeThread on the game thread, or 2) set/reset an event from the process and have the game thread check it before processing the next frame.

Just my thoughts on the matter.

Share this post


Link to post
Share on other sites
Painful? Hardly.
#define RET_CHK(x) if(!x) return false
Both methods are simple, and provide equal performance.
It''s a matter of which method you find quicker/easier to use - which really leaves it up to opinion.

Share this post


Link to post
Share on other sites
Your method still requires more code, both in the function call and function bodies.

I have a quick question for you. Which of the following three styles of setting a data member would you prefer:

1) point.set_x(x);
2) point.x(x);
3) point.x = x;

Share this post


Link to post
Share on other sites
point.x = x gives a better view of what it does.

If you look more closely at Magmai''s code, you''ll see that when a quit message is sent, it can be up to five seconds before the game starts to close. Basically, the game doesn''t co-operate immediately with the quit message unless you check for the g_evExit flag within function bodies... which of course requires large return value chains.

Share this post


Link to post
Share on other sites
Well, I'd say if you check for closing once every frame that would be quite enough for the player to think the game stopped right the same instant he/she pressed the quit button. And if we take a close look at Magmai's code we'll see that he gives the thread 5 seconds to quit nicely and after that he kills it. If it takes 5 seconds then something is probably wrong (unless your close-down code takes forever).
Some problems with the ProcessMessage() (depending of how it is implemented):
If ProcessMessage() process only 1 message each time it's called the message queue could be flooded by messages in the worst case (many messages sent, framerate low).
Else if ProcessMessage() processes all messages each time, it could decrease, or worse, give huge differences in framerate, which would make the game seem choppy in the worst case (bursts of messages distributed unevenly).
So the best thing (in your case) would be to process a constant amount of messages each frame (probably more than 1).

Edited by - amag on February 26, 2001 8:12:27 AM

Share this post


Link to post
Share on other sites
If a flood of messages is sent, there''s nothing you can really do about it. It''s quite common in even professional games these days for the game to drop a few FPS for a moment. Not that you should be receiving that many messages normally anyway. With your suggestion, you could stretch it out, but that would only distribute the FPS loss over several frames. If you were using the multithreading code, then all the messages would be processed at once...

The purpose of trying to code in ol'' dos style, is so that, for example, in an rpg, you could have a function to display a series of text messages in a series of boxes, and the function only returns when the box has been closed. Now for long text messages, that could take quite a length of time - and it is not uncommon for text messages to go for longer than five seconds. Let''s say the gamer is living with his parents. He has ust started a lengthy conversation with an NPC, when his parents call him to dinner. He presses alt-F4. He waits for the damn thing to shut down. Get the idea?

In a simple 2d game I''m working on, I have included message handling in a function merely called "Sync()". This updates some keyboard-related flags, handles messages, waits for a vertical blank, and flips the buffers. I also use a macro, SYNC, defined as "if(!Sync()) return false". The rest of the return value chains are manual, but the functions don''t run very deep, and there aren''t many of them. Macros help out, though.

Share this post


Link to post
Share on other sites
quote:

First of all calling WaitForXXX() can cost up to 400 CPU cycles as it transitions to kernel mode and back. That''s a good way to lower your framerate, especially if you are calling WaitForXXX each frame!


Hm, let''s do a calculation: 400 CPU cycles, and on a reasonable low-end (of todays standard) computer, a PII 400 Mhz, will 400 cycles take appr. 1us (since 1 cycle/s == 1 hz, thus the above computer would be capable of 400M=400*10^6 cycles per second). Do you really expect 1us per frame (saying we display 60 frames per second) will decrease the framerate noticably? I don''t think so.
This is what pre-mature optimisation means, optimising on the wrong places, just because you believe it is slow.

Beer Hunter:
What you don''t seem to realise is that an even frame-rate (although low) is much prettier than a jumpy one. It''s far better to have an even 30fps than to have 60 that drops to 40 every once in a while, since the drop in frame-rate is much more disturbing and noticeable.
If I was to use multi-threaded code the message-pump thread would have it''s time-share of the CPU-time to process messages, so to that thread it will look like it processes all messages at once, but it will be interrupted by other threads (or rather the scheduler), so it would probably be a smoother way.
And about that boy, does he really have to wait for the program to close down ? Besides it''s pretty easy to say that the lengthy conversation should be ended if the player quit''s, even if you use threads.

Share this post


Link to post
Share on other sites
A modal dialog box might be alright for a simple 2D game, but what if you want to have animations going in the background? And if you''re streaming sound you have to update the buffer, right? You can''t just sit there polling "while( not dialog.done() );" - it''s just to simplistic. And what about other apps? You''re just wasting what could have been their CPU time.

Threads could really clean that code up and raise its efficiency. They are useful for the main message loop, audio, and anything else that can truly occur asynchronously. But they''re not magic; you have to use them properly.

Share this post


Link to post
Share on other sites

  • Advertisement