Hi,
I was trying out the threads library when I ran into
the following problem. When using a bounded buffer
(the one from the example) the system locked up if
I had more then one reader and I started the readers
before the writers. With only one reader, or if I
started the writer thread first, it all seemed to
work fine. Also changing the notify_one to notify_all
made it work again.
When I looked into the implementation of the condition
variable (Which is non-trivial, to say the least) I found
that in both notify_one and notify_all not all control paths
release the m_mutex member, it is allways locked, but
in one specific case is never unlocked.
This also happes for the m_gate member, but is unlocked in
other functions (were it is never locked). I could not find
such a case for the m_mutex member. The code in question
is:
void condition::notify_one()
{
unsigned signals = 0;
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
return;
}
++m_waiting;
--m_blocked;
// NEVER UNLOCKED
}
else
{
...snip...
}
}
If m_waiting != 0 and m_blocked != 0 then m_mutex is never unlocked.
if add the release at the location of the comment everything seems
to work. But, unfortunately, that proves nothing in multitreaded
programs. Locking m_mutex and not unlocking it seems wrong to
me, but given the implementation I could be missing something.
So is this a bug in the code, or a bug in my head?
Rob Lievaart.