Of course there's a horrible flaw in both CoWaitForMultipleHandles and
MsgWaitforMultipleObjectsEx: if you do a 'wait all' and there's a
message pump involved, it'll only return when all the handles are
signaled *and* you've got at least one message waiting for you in the
call.

Ahhh, the memories... here's a blast from the past (in unmanaged C++, of course)

// This function mimics the up-and-coming CoWaitForMultipleHandles
function but returns the DWORD result of
// WAIT_OBJECT_0 for handle zero, etc..., or WAIT_ABANDONED_0 for
abandoned handles, or
// WAIT_TIME if timeout expires
DWORD NiceWaitForMultipleHandles(
 BOOL fAll,         // Wait options, FALSE waits for any, TRUE waits
for all messages...
 DWORD dwTimeout,   // Timeout period, in milliseconds.
 ULONG cHandles,    // Number of elements in the pHandles array.
 LPHANDLE pHandles) // Array of Win32 handles.
{
  DWORD dwResult = WAIT_FAILED;
  DWORD dwTimeLeft = dwTimeout;
  static const DWORD dwOneSlice = 100; // do it in 100 millisecond chunks...

  while (1)
  {
     if ( ! fAll)
     {
        dwResult = MsgWaitForMultipleObjects(cHandles,      // number
of handles in the handle array
                                             pHandles,      //
pointer to the object-handle array
                                             fAll,          // any or all flag
                                             dwTimeout,     //
time-out interval in milliseconds
                                             QS_ALLINPUT);  // type
of input events to wait for (any input)

        if (dwResult == WAIT_OBJECT_0 + cHandles)
        {
           // We have input messages, dispatch them!
           MSG msg;

           while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD))
           {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
           }

           // When we service messages, let's not count that against
the timeout specified so loop back...
           continue;
        }
     }
     else {
        // MsgWaitForMultipleObjects is broken if ALL is chosen.
Deal with it the hard way...

        // if we are not doing an instant check
        if (0 != dwTimeLeft)
        {
           dwTimeout = dwOneSlice;

           if (INFINITE != dwTimeLeft)
           {
              if (dwTimeLeft < dwTimeout)
                 dwTimeout = dwTimeLeft;

              dwTimeLeft -= dwTimeout;
           }
        }
        else
           dwTimeout = dwTimeLeft;

        dwResult = WaitForMultipleObjects(cHandles,      // number of
handles in the handle array
                                          pHandles,      // pointer
to the object-handle array
                                          fAll,          // any or all flag
                                          dwTimeout);    // time-out
interval in milliseconds
     }

     if ((WAIT_OBJECT_0 <= dwResult) && (dwResult < (WAIT_OBJECT_0 +
cHandles)))
     {
        // Success on one/all handles
        break;
     }
     else if ((WAIT_ABANDONED_0 <= dwResult) && (dwResult <
(WAIT_ABANDONED_0 + cHandles)))
     {
        // One or more handles abandoned
        break;
     }
     else if (dwResult == WAIT_TIMEOUT)
     {
        // If we were waiting for ANY, or used up the whole timeout,
        // we know it is a "hard" timeout...
        if ( ! fAll || (0 == dwTimeLeft))
           break;

        MSG msg;

        // Service the queue without yeilding...
        while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD))
        {
           TranslateMessage(&msg);
           DispatchMessage(&msg);
        }

        // Note, we could adjust the dwTimeLeft to account for the
time spent dispatching
        // messages, but in most cases we don't really care...
     }
     else break; // something I don't expect
 }

  return dwResult;
}

--
"You hide yourself with sanctimony, I hide myself with narcissism."
--T-Bone Burnett

Marc C. Brooks
http://musingmarc.blogspot.com

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to