I have a function that waits for operations occurring on a non-blocking
socket to complete before returning to a caller. I use
MsgWaitForMultipleObjects() with the dwWaitMask parameter set to
QS_ALLINPUT. With these settings, MSDN's help text says that the following
conditions should cause MsgWaitForMultipleObjects() to return: any mouse or
keyboard activity, any repaint or timer messages, and any messages sent or
posted to the thread that makes the MsgWaitForMultipleObjects() call. I'm
assuming that the Winsock layer executes in its own context/thread when it
posts messages like FD_WRITE, etc. to the application that opened the
socket. If so then my code should do what I intend it to do and not "lock".
You see the code does work propertly, but I want to make sure that it isn't
really "locking up" until a paint or timer message comes along, resuming
execution and allowing the main thread to process the socket messages.
Any info appreciated.
thx
What Delphi version, Robert? If D6 and if the socket class you are using does
use Synchronize to fire the socket events in the main threads context then
your wait will block until some message wakes it up. That is OK since calling
Synchronize in an EXE (*not* in a DLL!) will post a WM_NULL message to the
application window. But the synchronized events would never fire unless you
call checkSynchronize after Application.ProcessMessages.
Since you say it works i assume you are using an older Delphi version. Just be
aware of the porting nightmare ahead if you ever update <g>.
--
Peter Below (TeamB)
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be
I'm using D6 Pro, service pack 2. But, if the socket message (FD_WRITE,
etc.) originates in a different context/thread, like I'm assuming the
originating Winsock layer would be, then wouldn't it trigger the following
events:
- a return from my MsgWaitForMultipleObjects(,,,,QA_ALLINPUT) which then
does
- A ProcessMessages() since it isn't the Windows message my loop is waiting
on, which hypothetically would
- Allow the socket class's event handlers to process the message that
originated from Winsock?
Wouldn't that sequence of events allow the code to function normally? My
original thread shows the exact code (mine, not the 3rd party socket class)
if that would help.
Thanks.
If the socket thread uses messages to communicate with the main thread you
have no problem. If it uses Synchronize you will have one since
ProcessMessages does not call CheckSynchronize. The Synchronize mechanism was
totally changed in D6. The old one worked by sending a custom message to
window in the main thread, the handler of the message then executed the
synch'ed method, whose address was passed as message parameter. The D6
mechanism creates a small object that contains a windows event object and add
this to a thread-safe queue. Then the thread calls a global callback and
finally waits for the event to signal. For a standard EXE the callback will be
implemented by Application.WakeMainThread, which posts a WM_NULL to the
Application.handle. This is only there to get the main thread out of a
WaitMessage call it may be sitting in. The main thread then handles the
message and finally calls Application.Idle if no more messages remain. Idle
calls CheckSynchronize and that method gets the stored synchronization objects
off the queue and calls the method pointer stored in them, then signals the
objects event to wake up the waiting thread.
The main point to keep in mind is that ProcessMessages does not result in a
call to Idle, so queued synchronization objects are not processed by it. And
in a DLL there is no handler for the WakeMainThread callback! Unless you
implement one yourself a thread in a DLL will deadlock if it calls
Synchronize...
Peter,
I don't believe the socket class is using CheckSynchronize() but I'll
double-check with the author. Amazing reply! Where did you get that kind
of detailed knowledge?
thx
By using the Source, of course <g>.
If the socket thread uses messages to communicate with the main thread you
have no problem. If it uses Synchronize you will have one since
ProcessMessages does not call CheckSynchronize. The Synchronize mechanism was
totally changed in D6. The old one worked by sending a custom message to
window in the main thread, the handler of the message then executed the
synch'ed method, whose address was passed as message parameter. The D6
mechanism creates a small object that contains a windows event object and add
this to a thread-safe queue. Then the thread calls a global callback and
finally waits for the event to signal. For a standard EXE the callback will be
implemented by Application.WakeMainThread, which posts a WM_NULL to the
Application.handle. This is only there to get the main thread out of a
WaitMessage call it may be sitting in. The main thread then handles the
message and finally calls Application.Idle if no more messages remain. Idle
calls CheckSynchronize and that method gets the stored synchronization objects
off the queue and calls the method pointer stored in them, then signals the
objects event to wake up the waiting thread.
The main point to keep in mind is that ProcessMessages does not result in a
call to Idle, so queued synchronization objects are not processed by it. And
in a DLL there is no handler for the WakeMainThread callback! Unless you
implement one yourself a thread in a DLL will deadlock if it calls
Synchronize...
Peter,
I don't believe the socket class is using CheckSynchronize() but I'll
double-check with the author. Amazing reply! Where did you get that kind
of detailed knowledge?
thx