|
Boost : |
From: Anthony Williams (anthony_w.geo_at_[hidden])
Date: 2006-12-11 04:06:06
Yuval Ronen <ronen_yuval_at_[hidden]> writes:
> Anthony Williams wrote:
>> Yuval Ronen <ronen_yuval_at_[hidden]> writes:
>>
>>> Roland Schwarz wrote:
>>>> Yuval Ronen wrote:
>>>>> I will gladly put my code here to be scrutinized by the experts on this forum (after the weekend, as the code is at work, and I'm
>>>>> at home now :-) ), but I fear that they will little incentive to do it.
>>>> Can't tell. Possibly yes. You will need to try.
>>> Ok, if anyone is still interested, here's my implementation of CV for Windows. It's very simple, maybe too simple, and I guess it's
>>> far less interesting than the code just posted by Chris Thomasson, but here it is anyway.
>>>
>>> void wait()
>>> {
>>> assert(m_mutex.isLocked());
>>> m_waitersCount++; // line A
>>> m_mutex.unlock();
>>> m_sem.lock(); // line B
>>> m_mutex.lock(); // line C
>>> }
>>>
>>> void broadcast()
>>> {
>>> assert(m_mutex.isLocked());
>>> if (m_waitersCount > 0)
>>> {
>>> m_sem.unlock(m_waitersCount); // line D
>>> m_waitersCount = 0;
>>> }
>>> }
>>
>> Unfortunately, it is susceptible to the "stolen wakeup" problem. If
>> m_waitersCount is non-zero, the semaphore is incremented on line D. This will
>> wake the appropriate number of waiting threads, but not immediately. Threads
>> waiting on a semaphore will not be woken until they are next scheduled. Thus,
>> a new thread might call wait, increment the waitersCount (line A) and acquire
>> the (line B) before all the threads currently waiting have been woken.
>
> I have to admit that I didn't understand the problem. Your description
> sounds exactly like what should've happen. At the end, all threads that
> were waiting before the call to broadcast() are woken, and the new
> thread is waiting. Just as it should. What have I missed?
Thread A:
locks mutex
Enters wait()
Runs line A, waitersCount=1
Unlocks mutex
Runs line B, blocks.
Thread B:
locks mutex
Enters wait()
Runs line A, waitersCount=2
unlocks mutex
Runs line B, blocks.
Thread C:
locks mutex
Enters broadcast()
Runs line D: Unlock semaphore(2) // 2 threads waiting
waitersCount=0
unlocks mutex
Thread A:
wakes on line B, sem count is now 1
locks mutex on line C
unlocks mutex
Thread D:
locks mutex
Enters wait()
Runs line A, waitersCount=1
unlocks mutex
Runs line B, sem count is 1, so acquires it and sets to 0
locks mutex on line C
Thread B:
remains blocked on line B
Thread D has stolen the wakeup intended for thread B, even though it entered
"wait" after the broadcast.
Anthony
-- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk