Re: COM objects waiting on a shared resource
Jason S <jmsachs@gmail.com> wrote:
Right. I imagined the same thing. So the threads A and B will do
something like this:
WaitFor(event);
WaitFor(mutex);
ResetEvent(event);
DoSomething();
ReleaseMutex(mutex);
Thread C will just do
SetEvent(event);
at which point both A and B wake up, but only one of them gets the
mutex. Some time later, the other one gets the mutex.
Hmmm... I am suspicious. I am not sure where to look to see if there's
any guaranteed maximum time for how long a kernel APC call could take
to distract one of my processes. Suppose A and B are waiting for the
event, then kernel "distracts" thread B, then C does SetEvent(), then
A executes the WaitFor(event)/WaitFor(mutex)/ResetEvent(event)
sequence, then the kernel is done with thread B. This means thread B
will miss the event altogether. If the event only happens once, then
thread B will hang.
I thought about it a little more, and here's my design. Condition
variables have four methods: Enter, Exit, Wait and Notify. One group of
threads does
Enter
while (!condition) Wait
DoWork
// the condition may or may not be true here
Exit
The other group of threads goes
Enter
DoWorkThatMakesConditionTrue
Notify
Exit
To implement this, I'll have two kernel objects. A manual reset event is
singalled whenever the condition is or may be true, and is non-signalled
whenever the condition is known to be false. A mutex (or critical
section, if done within a single process) guarantees that only one
thread at a time can check or change the condition (or any other shared
data). The implementation goes like this:
Enter() {
WaitFor(mutex);
}
Exit() {
ReleaseMutex(mutex);
}
Wait() {
// By the very fact of the thread calling Wait, we know that
// a) it currently owns the mutex, and
// b) the condition is false
// Indicate that the condition is now known to be false
ResetEvent(event);
ReleaseMutex(mutex);
// Wait for the condtion to (maybe) change
WaitFor(event);
// Reacquire mutex
WaitFor(mutex);
}
Notify() {
// Indicate the condition is now true. That'll wake up all the
threads
// sitting in Wait
SetEvent(event);
}
I believe this avoids any problems with PulseEvent or
SetEvent/ResetEvent in quick succession. ResetEvent is only called once
the condition is checked and found to indeed be false. There's also no
race condition between SetEvent and ResetEvent, since both calls are
done from inside the mutex.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925