I wonder whether there's a difference between those two snippets:
One:
void main()
{
// ...
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ExitProcess(0);
}
// ...
void quit()
{
PostQuitMessage(0);
}
Two:
bool quit = false;
void main()
{
// ...
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if(quit)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&_msg);
}
ExitProcess(0);
}
}
// Shouldn't get here
ExitProcess(1);
}
// ...
void quit()
{
quit = true;
PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
}
Sorry but I couldn't come up with shorter snippets.
The point of my question is whether calling PostQuitMessage and processing all messages with GetMessage is equivalent to processing all messages with PeekMessage, until it returns FALSE.
According to Raymond, WM_QUIT is "generated only when the message queue is otherwise empty", so it looks like the two methods should do the same, but perhaps there's a subtle difference.
Raymond's blog post says:
Because the system tries not to inject a WM_QUIT message at a "bad
time"; instead it waits for things to "settle down" before generating
the WM_QUIT message, thereby reducing the chances that the program
might be in the middle of a multi-step procedure triggered by a
sequence of posted messages.
So in theory no, there is no difference, because the system won't generate WM_QUIT until the queue is empty. However Raymond doesn't say that it's guaranteed that messages won't arrive after WM_QUIT is generated, only that the system tries to avoid it.
Therefore it's conceivably possible that another thread could post you a message after you've exited your main GetMessage loop, and depending on your application this may be something you have to deal with. For example, if you post messages internally with memory allocations that the receiving thread is expected to free, you may need a separate PeekMessage loop to clean them up before the thread exits completely.
In practice however no one ever writes message loops like your second example.
I don't think the accepted answer addresses the real issue.
Raymond answers this question directly here.
Basically:
You do not have control over every message loop, so you don't have that option.
Oh, and by the way, don't forget to PostQuitMessage inside your own message loops.
Note that even WTL neglects to do this!
It relies on you passing the return value of CMessageLoop::Run to PostQuitMessage.
Related
I'm creating a thread for my game. But I found, that if close button is pressed, or the task is killed I cannot properly finish the work, deallocating all the resources I needed inside the program.
I found that Close handler exists, but the example given is an unknown magic to me, because I need to create something similar in ANSI-C.
static BOOL CloseHandler(DWORD evt)
{
if (evt == CTRL_CLOSE_EVENT)
{
m_bAtomActive = false;
// Wait for thread to be exited
std::unique_lock<std::mutex> ul(m_muxGame);
m_cvGameFinished.wait(ul);
}
return true;
}
I know that Winapi has Mutex and conditional variables, but I do not know anything about std::atomic equivalent.
I have this thread start function and inside thread function GameThread I have a regular bool variable m_bAtomActive checked now.
void Start(void* _self)
{
DWORD dwThreadID;
HANDLE hThread;
struct c_class* this = _self;
this->m_bAtomActive = true;
hThread = CreateThread(
NULL,
0,
&GameThread,
_self,
0,
&dwThreadID);
WaitForSingleObject(hThread, INFINITE);
}
I'm bad at threading, what should I do to properly finish the work of my game?
All the additional details will be provided in the comments or on the chat.
UPD: The first thing seems to be easy, it is solvable with this line inside close handler
if(Active)
InterlockedDecrement(&Active);
But the second and third is still under question. They might be created for the reason of CloseHandler killing the app before destruction, but I don't know for sure.
Could someone explain why I never receive a WM_COMMAND message in my GetMessage loop?
I've checked and the WndProc is receiving the WM_COMMAND message, so i'm very confused why this doesn't work.
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_COMMAND)
{
// This never happens:
MessageBox(NULL, "WM_COMMAND", "WM_COMMAND", MB_OK);
}
}
OS: Windows 8
Because WM_COMMAND is sent with SendMessage(). Which directly calls the window procedure. Only messages posted with PostMessage() get added to the queue and are retrieved by GetMessage().
You can see this back in a utility like Spy++, it annotates messages that are posted with P and messages that are sent with S.
I want my code to be able to handle the error cases, such as unsuccessful return of functions. For instance,pthread_create,normally I use the function herebelow:
int thread_check1;
pthread_t function;
thread_check1 = pthread_create( &function, NULL, function_function, NULL);
if(thread_check1 != 0){
fprintf(stderr, "pthread_create error\n");
exit(1);
}
Considering the error cases, would it be correct to call the same function till it returns 0(for this specific function) as it is done below?
thread_check1 = pthread_create( &function, NULL, function_function, NULL);
while(thread_check1 != 0){
thread_check1 = pthread_create( &function, NULL, function_function, NULL);
}
Can I apply the same logic to the other C functions that returns a value? Otherwise, how would you suggest to handle error cases (for the function returns) without exiting from the program?
You could do that, but more properly. Assume there is function f which has different return values. You can do as follows:
tries_left = 1000;
do
{
ret = f(params);
if (ret == OK)
break;
else if (ret == SOMETHING_UNRECOVERABLE)
/* break with failure */
else if (ret == SOMETHING_FIXABLE)
/* fix params */
else
/* sleep a little */
} while (--tries_left);
There are many things to consider here:
Avoid infinite loop. If there is something inherently wrong, you wouldn't want to get stuck in a loop. So after some tries, you would want to break and fail. This is where tries_left comes into play.
Fail if unrecoverable. If the error tells you that the problem is not fixable, stop trying. For example if you are trying to mount a drive and it tells you /dev/sda6 doesn't exist, there is no point in retrying.
Try actually handling the problem. In some cases, you may be able to try different parameters. For example if you are trying to create a backup file and you can't, you can try changing the directory or name of the file and try again.
Don't use 100% CPU. If you want to retry, at least give some breathing room in between tries for whatever problem there was to go away, or in the very least to avoid using maximum CPU.
In the end, to avoid repeating yourself if you have different functions that need to be handled like this, you could put this whole thing in a macro and call it like CHECK_AND_RETRY(f(params));, assuming it is possible to understand what return value is unrecoverable and what is fixable no matter the function (kind of restrict, but there is no beautiful solution).
As Joe already mentions it heavily depends on your requirements and on the method you want to use. Whenever something fails there's usually a reason. For example no more memory is available if malloc returns zero.
Trying to get new memory without actually using free under such circumstances will usually result in an infinite loop, so that's something you shouldn't do. On the other hand, when you want to open a file but it's currently blocked by another process you could do something similar.
However, keep in mind that such a loop will usually keep the CPU busy and slow down other processes/threads. Also you could use a thing between your current solutions and try several times before you exit:
error_count = 0;
thread_check1 = pthread_create( &function, NULL, function_function, NULL);
while(thread_check1 != 0){
sleep(1); // wait some time before we try again
if(++error_count == 10){
fprintf(stderr, "Could not create thread\n");
return 1;
}
thread_check1 = pthread_create( &function, NULL, function_function, NULL);
}
What should be done in case of failure depends solely on your requirements.
Usually it will depend on type of the error (fatal, acceptable etc.) and it's impact on the program.
Getting back to your example, failure to create thread should probably be treated as fatal error since the issue that prevented it's creation will most likely not go away on second or third attempt (again, it depends on your requirements and environment) thus not looping is probably a better approach here. Yet again, whether you want to quit the program or not in case of failure is up to you - can your program continue running without this thread? If yes, terminating the program isn't necessary. Otherwise - terminate.
I would definitely not recommend handling errors like that. In the case there is a genuine problem you will be stuck in an infinite loop. An example is opening a file when it is already in use. I would say you should do one of the following:
Print/Log the error and stop execution.
Allow certain errors (Add a && to the if), this example would retry only if the error code is 3
if (thread_check1 != 0) {
If (thread_check1 == 3) retry;
Working with C and Win32, I have a problem where my program freezes instead of closing when a quit message is posted(Alt-F4 for example), and I have to end the process with task manager.
I have this in my main loop:(problem solved)
MSG msg;
while(1)
{
while(PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
terminate = 1;
while(terminate != 3) //each thread increments "terminate" by 1 before returning
{
Sleep(1);
}
return 0;
}
DispatchMessage(&msg);
}
Sleep(1);
}
It will print "OK!" in the console and then freeze.
I think this could be because I have multiple threads and they are not terminated properly (but I read that if I return from my main() function the other threads should be killed automatically). If it helps one of those threads is an OpenGL rendering thread.
The main function is only just a thread, you are terminating just that one. However, for a process to end, all threads need to be properly terminated or it will run forever. You'll need to keep a reference the threads and terminate them once you receive the WM_QUIT message.
Exit is to exit from the entire process. Your process will clean up when you call exit, e.g. Call the function registered with atexit, or call destructor of global object in case of c++. What about abort(), or terminateProcess.
I have a thread like this:
DWORD WINAPI message_loop_thread(LPVOID dummy) {
MSG message;
while (GetMessage(&message, NULL, 0, 0)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
}
And i start it with CreateThread:
DWORD thread_id;
CreateThread(0, 0, message_loop_thread, 0, 0, &thread_id);
This seems to work, but how can i correctly close this thread? Normally the thread is waiting for GetMessage so the thread is blocked i think.
Is there a good way to do this? I tried TerminateThread, but this hangs, and i think it's not a good solution to stop the thread.
Has someone an idea?
best regards
Benj Meier
The proper way is to post WM_QUIT to thread_id. You use PostThreadMessage() for this. In response, GetMessage returns 0, the while loop exits, and the function exits (incorrectly, you're missing a return statement). When the toplevel function of a thread exits, the thread ends.