views:

1224

answers:

3

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.
}
+3  A: 

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 - 1))
{
    firstSignaled = ret - WAIT_OBJECT_0;
    for (i = firstSignaled + 1; i < count; i++)
    {
        if (WaitForSingleObject(handles[i], 0) == WAIT_OBJECT_0)
        {
           // Signaled!
        }
    }
}
Michael
Yes do this after the waitformultipleobjects call
Brian R. Bondy
Thanks for the suggestion, added pseudocode to show this.
Michael
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
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
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
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
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
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
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
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
Besides the first signaled event, the events will signalled when WaitForMultiple returns.
Michael
A: 

One other option you might have is to use RegisterWaitForSingleObject. The idea is that youyou flag the signalled 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.

Larry Osterman
A: 

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.

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