MsgWaitForMultipleObjects/QS_ALLINPUT revisited

0 views
Skip to first unread message

Robert Oschler

unread,
Jun 26, 2002, 12:56:36 PM6/26/02
to
I posted this question in a different form on another thread, and I don't
think I did a good job of phrasing the question. Here's clearer formulation
of the question:

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


Peter Below (TeamB)

unread,
Jun 26, 2002, 5:19:10 PM6/26/02
to
In article <3d19f2fb$1_1@dnews>, Robert Oschler wrote:
> I posted this question in a different form on another thread, and I don't
> think I did a good job of phrasing the question. Here's clearer formulation
> of the question:
>
> I have a function that waits for operations occurring on a non-blocking
> socket to complete before returning to a caller.

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


Robert Oschler

unread,
Jun 26, 2002, 10:42:46 PM6/26/02
to

"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote in message
news:VA.00008da...@antispam.compuserve.com...

> In article <3d19f2fb$1_1@dnews>, Robert Oschler wrote:
>
> 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.
>
Peter,

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.


Peter Below (TeamB)

unread,
Jun 27, 2002, 3:12:50 PM6/27/02
to
In article <3d1a7c5b_1@dnews>, Robert Oschler wrote:
> 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?

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...

Robert Oschler

unread,
Jun 28, 2002, 10:14:37 AM6/28/02
to

"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote in message
news:VA.00008db...@antispam.compuserve.com...
> <...>. 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

Peter Below (TeamB)

unread,
Jun 28, 2002, 3:16:46 PM6/28/02
to
In article <3d1c6ffc$1_1@dnews>, Robert Oschler wrote:
> Where did you get that kind
> of detailed knowledge?
>

By using the Source, of course <g>.

Peter Below (TeamB)

unread,
Jun 27, 2002, 3:12:50 PM6/27/02
to
In article <3d1a7c5b_1@dnews>, Robert Oschler wrote:
> 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?

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...

Robert Oschler

unread,
Jun 28, 2002, 10:14:37 AM6/28/02
to

"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote in message
news:VA.00008db...@antispam.compuserve.com...
> <...>. 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

Reply all
Reply to author
Forward
0 new messages