Reputation: 1195
I am working with a class that starts and ends a thread. The thread is created in the constructor. The thread function has a loop that continues as long as a flag is TRUE. The flag is a static member of the class. The deconstructor sets the flag to FALSE. This way, each instance of the class has an associated thread that runs for the lifetime of the instance.
I am trying to wrap my head around what happens when the deconstructor runs, and if this is an okay way to end the thread. I do not have much experience with multithreading.
Here's what I think happens. Inside the deconstructor, the flag will be set to FALSE. Let's assume Sleep() is running for infinity. The object is destroyed, but the flag still exists in memory because it is static. But the entire process is ending, let's say, so at some point the static flag will disappear. Will the flag disappear before the thread? If the thread is forced to return by the process ending, does the thread even care about the flag any more? I don't know what takes place at this point.
I am using Visual C++ in Visual Studio 2010.
Upvotes: 3
Views: 3843
Reputation: 24857
It depends on whether the 'deconstructor' actually runs at all.
If you attempt to 'deconstruct' the objects you describe in some 'OnClose' event-handler, setting the static flag will instruct the threads to terminate if they get around to checking it. If they do not, the threads will continue to sleep, (or remain stuck on whatever call is blocking, or continue to run code).
If you take no further action to wait for object-thread termination, the main GUI thread will run on, destroy all its GUI objects etc. and and call ExitProcess().
Once ExitProcess() is called, the OS will stop ALL threads of the process, no matter what state they are in, before deallocating any memory, (like the memory containing your flag).
The thread that calls ExitProcess() never has control returned to it. Other threads that belong to the same process, and are not running on another core, have their state set so that they are never run again. Other threads that belong to the same process, and are running on another core, have the core that they are running on hardware-interrupted to stop the threads.
Will the flag disappear before the thread?
No. The thread/s will be stopped before the memory hosting the flag is deallocated.
If you do not wish this forced-termination to occur, you must take action to await the actual termination of the object-threads. You have to delay the main GUI-thread from calling ExitProcess by setting an appropriate CloseAction in the OnClose handler. The GUI thread should only close/release itself when all the object-threads have terminated and the objects' destructors have completed.
If I really, really, really have to do this, prefer to do it by PostMessaging a 'WM_THREADGONE' Windows message to the main GUI thread, (as the last action of the object-threads before actually terminating themselves), and counting down a 'threadCount' towards zero in the message-handler, so keeping the GUI thread available to handle messages until all object-threads have terminated themselves. Hard-Wait mechanisms, like Join(), are just deadlock-generators that have a huge capacity for shutdown problems and should not be used.
I usually try to work around all thread termination issues by designing my apps so that sudden, involuntary thread termination is an acceptable action then and let Exitprocess() blow everything away. This is not always possible, but it's a pile safer if you can get away with it.
Upvotes: 0
Reputation: 3911
Note that running destructor while some other thread is still in use of that object (not the static flag) will produce undefined result.
Think what happen when the thread is in middle of processing instead of checking the alive flag, pretty slim chance huh.
It is better to write a stop(bool wait) function, so if destructor is call and required to auto clean up, you set the flag to stop, and block until the thread to set another flag to "stopped", or just join that thread with pthread_join (not recommended, see below).
Furthermore, when you block for graceful termination you may also set a timeout, and force terminate the thread if something goes wrong (and generate alarm for debug).
Upvotes: 2
Reputation: 754763
On Windows a thread has a lifetime which is less than or equal to the process in which it is cerated. Hence once the process ends so does the thread.
A normal process shutdown won't complete until all of the threads in that process terminate. Hence in this case the flag will be set, the main thread may terminate but the created background threads will continue running. Eventually they will see the FALSE
value of the flag, exit their loop, complete and the process shutdown will be complete.
Upvotes: 2