what happens if a manual-reset event is set using setEvent but not reset using ResetEvent; and that event is triggered multiple times.i.e. while the event is getting processed, again the event is set.
following is the sample task:
void foo()
{
...
SetEvent(hEvent1);
...
}
void foo1()
{
...
SetEvent(hEvent2);
...
}
int MainHandler()
{
...
dwEvent = WaitForMultipleObjects(2,
ghEvents, // array of objects
FALSE, // wait for any object
5000);
switch(dwEvent)
{
case hEvent1:
//do something
break;
case hEvent2:
//do something
break;
}
}
Now, suppose while hEvent1's case is executing(i.e. it is still set), somehow again hEvent1 is triggered. I have deliberately not put ResetEvent(hEvent1) even though it is a manual-reset events. So, do we have a race condition?
In your example using
WaitForMultipleObjects
, you may have a potential problem if the events you are waiting on are not listed in increasing order of frequency in the array of event handles. Also note my comment that your code above assumes thatWaitForMultipleObjects
returns an event handle. It doesn't.WaitForMultipleObjects
will stop waiting when the first signaled event is seen, looking at the array from index zero upwards.So if you have an event that gets set (or does not get reset) as the first entry in the array, then the other events will get starved (i.e. will never be seen).
So, in your example, as long as
hEvent1
is still signaled,hEvent2
will not be seen.As an example of a common pattern, suppose we have some worker thread, whose thread function has been routed back to some owning class that contains the event objects and mutexes or whatever. The worker thread responds to just two events - a request to close tidily and a request to do some work. The code might look something like this:
As coded, this will work fine - the main thread calls
SetEvent(m_hWorkEvent)
to trigger the background thread to do some work and it callsSetEvent(m_hKillEvent)
to make the worker thread close. Closing may be protected with some timeout in case the thread is mid-work, so something like:Now, this closedown process will work fine, even if
m_hWorkEvent
is being signalled very frequently - for example, by the timedo some work here
has finished, the event has again been signalled. This is becauseWaitForMultipleObjects
will always check the kill event first because it is the first one in the array.However, if the array had been defined like this:
And if
m_hWorkEvent
is continually signalled (e.g. it gets set again during a long-runningdo some work here
, or it is a manual reset event and you never reset it), then the thread will never exit cleanly because it will never see the kill signal. It will always try to do some work first.This is what I mean about ordering the events in the array in increasing order of frequency. The kill event has the lowest frequency (it is signaled only once), so it goes first. If you have three or more events for different work requests, you need to maintain the same ordering or some events will get starved.
Whatever you decide to do, it's also worth noting that even if
WaitForMultipleObjects
got release on the "wrong" event, you can still check if a particular event is signaled by waiting with a zero timeout:This can allow you to put intermediate checks for a kill event in suitable parts of a long-running background work procedure.