If I'm using Boost in a single threaded app, do I need to define BOOST_DISABLE_THREADS to avoid Boost using locks, etc. internally?
You don't need to, but it may remove some redundent code, if your app is single threaded *and* links to a multithreaded runtime. - John Maddock http://ourworld.compuserve.com/homepages/john_maddock/
Hi, I've run into a fairly serious problem attempting to use boost::thread with the Windows UI. The problematic part of my application is a configure screen. One button allows the user to scan a hard drive for music files, which are loaded into an internal database. As this process takes a significant amount of time, I've placed the code that does the scanning in a separate thread. In order to make it obvious that things are happening, the scan thread uses SetDlgItemText to update display the current file being scanned on the dialog. This all works quite well. The problem comes in if the user tries to dismiss the configure dialog. Ideally, when the button is clicked, the code should signal the thread to quit, and then do a join for wait for it to finish before destroying the owning object. Unfortunately, because of the way the Windows UI works, this instead causes a deadlock. Basically, the trouble is that clicking the button that dismisses the dialog calls the Window Procedure from the message queue. Thus, while we are handling this button, no other messages get processed. Normally, this would be ok, as the thread should die within a few hundred milliseconds at most. The trouble is, though, that SetDlgItemText works by putting a message in the queue and then waiting for it to be processed. But the message won't be processed until the current message handler returns. The upshot of this is that the threads deadlock when join() is called. This is a common Windows problem, but it is solvable. For example, the Windows MessageBox() doesn't cause the rest of the system to hang if called in a message handler. The solution is for the main thread to process messages itself while it is waiting for the secondary thread to finish. So instead of doing a WaitForSingleObject() on the thread, you do a MsgWaitForMultipleObjects() on the thread. Then, if you are woken up for Windows messages, you process them and then go back to sleep. I've done this in pure Windows code, and it works well. For my current project, I'd like to use boost::thread, though, both because I intend to port to Linux and also because the boost thread implementation is much easier to deal with than the Windows one. Unfortunately, boost::thread::join() uses WaitForSingleObject(), which means that this deadlock issue rears its ugly head. The only solutions I've found short of modifying the boost code is to just delay a few seconds and hope to God the thread dies before the object that owns it does. Obviously this isn't a satisfactory solution! Is there anything else I can do? Steve
Steve, You brought up an interesting problem. Here are my thoughts on a possible solution: Rather than calling SetDlgItemText() and immediately starting a WaitForSingleObject(), instead you could create a user-defined message called, say, WM_USER_WAITFORTHREAD. Then, post a WM_USER_WAITFORTHREAD message to your HWND right after the SetDlgItemText(). Since the item-text change message was sent first, it should be executed before the thread-waiting message is processed. If you use MFC, you can either manually add a handler for WM_USER_WAITFORTHREAD into its message-mapping section or just override CWnd::PreTranslateMessage(). I apologize for the off-topic-ness of all this. Sorry :) -Jonathan
----- Original Message -----
From: Steve Burnap
thread. In order to make it obvious that things are happening, the scan thread uses SetDlgItemText to update display the current file being scanned on the dialog. This all works quite well.
... Which does a SendMessage which as you've found does not work quite well. I assume you are using a worker thread which should communicate with a UI thread via PostMessage, never SendMessage. Another method would be to have a time in the dialog that polls a memory location (properly guarded for read/write access.) Jeff
At 04:55 PM 2/24/02 -0500, you wrote:
----- Original Message ----- From: Steve Burnap
... thread. In order to make it obvious that things are happening, the scan thread uses SetDlgItemText to update display the current file being scanned on the dialog. This all works quite well.
...
Which does a SendMessage which as you've found does not work quite well. I assume you are using a worker thread which should communicate with a UI thread via PostMessage, never SendMessage. Another method would be to have a time in the dialog that polls a memory location (properly guarded for read/write access.)
Jeff
Using PostMessage would be nontrivial because the strings that I'd have to pass are currently locals. The second option sounds like it should work, though. Thanks! Steve
participants (4)
-
Jeff Flinn
-
John Maddock
-
Jonathan Brownell
-
Steve Burnap