5

Given: I fill up an array of handles with auto reset events and pass it off to WaitForMultipleObjects with bWaitAll = FALSE.

From MSDN: “When bWaitAll is FALSE, this function checks the handles in the array in order starting with index 0, until one of the objects is signaled. If multiple objects become signaled, the function returns the index of the first handle in the array whose object was signaled.”

So, now if multiple objects signal I’ll get the index of the first one. Do I have to loop though my array to see if any others have signaled?

Right now I have a loop that’s along the lines of:

For ( ; ; )
{
WaitForMultipleObjects(…)
If  (not failed)
     Process object that called. 
     Remove the handle that signaled from the array.
     Compact the arrary.
}
Martin Thompson
  • 16,395
  • 1
  • 38
  • 56
Chris
  • 53
  • 1
  • 1
  • 6

4 Answers4

5

Yes. One alternative would be that you could do WaitForSingleObject(handle, 0) on each handle which will return immediately and indicate if they are signaled or not.

EDIT: Here's sample pseudocode for what I mean:

ret = WaitForMultipleObjects()
if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + (count))
{
    firstSignaled = ret - WAIT_OBJECT_0;

    // handles[firstSignaled] guaranteed signalled!!

    for (i = firstSignaled + 1; i < count; i++)
    {
        if (WaitForSingleObject(handles[i], 0) == WAIT_OBJECT_0)
        {
           // handles[i] Signaled!
        }
    }
}
ratchet freak
  • 47,288
  • 5
  • 68
  • 106
Michael
  • 54,279
  • 5
  • 125
  • 144
  • Yes do this after the waitformultipleobjects call – Brian R. Bondy Mar 20 '09 at 18:27
  • The problem with that answer is you have basically turned on bWaitAll with that WaitForSingleObject. I don’t want to wait on all the handles, just service the ones that have signaled. – Chris Mar 20 '09 at 18:40
  • 2
    The timeout of 0 means that WaitForSingleObject does not wait. It checks the signaled status and returns immediately with WAIT_OBJECT_0 or WAIT_TIMEOUT. Or am I misunderstanding your statement? – Michael Mar 20 '09 at 18:42
  • You have the correct meaning. I was mistaken. From MSDN "If dwMilliseconds is zero, the function tests the object's state and returns immediately". What happens to handles that signal after I have evaluated them? I assume they will stay signaled and I’ll pick them up when I hit wait multiple again. – Chris Mar 20 '09 at 18:52
  • 1
    It depends on the type of handles. Manual reset events will stay signaled and need to be reset. Auto reset events will go back to unsignaled. Mutexes will be acquired after the WaitForSingleObject call - and so on. – Michael Mar 20 '09 at 18:54
  • I think that's the crux of my problem. These are auto reset events. So, it seems possible that I will be dropping events using this algorithm then. – Chris Mar 20 '09 at 18:58
  • If the objects you are waiting for are not inter-related (as in this simple example) what is the benefit of this, over just going back and doing the WaitForMultipleObjects call again (which should pick up the next signalled object). – Greg Rogers Mar 20 '09 at 19:17
  • Possible starvation - if handle[0], handle[1], etc., are frequently signaled WaitForMultiple may never get around to indicating handle[50], handle[51], handle[52], etc. – Michael Mar 20 '09 at 19:23
  • But the events will still be signaled if i loop back through waitformultiple? As long as im not worried about starvation then my orginal code smple works just fine. – Chris Mar 20 '09 at 19:25
  • Besides the first signaled event, the events will signalled when WaitForMultiple returns. – Michael Mar 20 '09 at 19:27
5

So, now if multiple objects signal I’ll get the index of the first one. Do I have to loop though my array to see if any others have signaled?

Why not just go back round into the Wait()? if multiple objects signalled, they will still be signalled when you come back round. Of course, if you have a very rapidly firing first object in the wait object array, it will starve the others; what you do is order your objects in the wait object array by frequency of firing, with the least frequent being first.

BTW, where you're using an endless for(), you could use a goto. If you really are not leaving a loop, an unconditional goto most properly expresses your intent.

  • This is effectively the solution used. The key I needed to figure out was “if multiple objects signaled, they will still be signaled when you come back round.” If I don’t have to worry about starvation then my original solution was fine. – Chris Mar 25 '09 at 18:40
  • 1
    Yes. WaitForMultipleObjects() scans the handle array from 0 onwards and returns as soon as it finds a signalled handle. Only that first found handle is reset to the unsignalled state; the others are untouched. –  Mar 25 '09 at 19:27
3

One other option you might have is to use RegisterWaitForSingleObject. The idea is that you flag the signaled state of event in a secondary array from the callback function and then signal a master event which is used to wake up your primary thread (which calls WaitForSingleObject on the master event).

Obviously you'd have to take care to ensure that the secondary array was protected from access by the main thread but it would work.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
Larry Osterman
  • 16,086
  • 32
  • 60
0

Only the auto-reset event that ended the wait (whose index is returned) will be reset. If the wait times out no events will be reset.

cf https://blogs.msdn.microsoft.com/oldnewthing/20150409-00/?p=44273

persiflage
  • 1,154
  • 12
  • 22