Boost logo

Boost :

Subject: Re: [boost] [Thread][Release] Boost.Thread and 1.45 release
From: Anthony Williams (anthony.ajw_at_[hidden])
Date: 2010-10-29 09:53:37


"vicente.botet" <vicente.botet_at_[hidden]> writes:

> From: "Anthony Williams" <anthony.ajw_at_[hidden]>
>> "vicente.botet" <vicente.botet_at_[hidden]> writes:
>>
>>> From: "Anthony Williams" <anthony.ajw_at_[hidden]>
>>
>>>> I've fixed all the outstanding "showstopper" bugs in boost.thread on
>>>> trunk (including the thread interruption issue, #2330),
>>
>>> I have take a look at the modification associated to this ticket #2330
>>> thread::interrupt() can be lost if condition_variable::wait() in
>>> progress and I don't reach to understand why do you need to have an
>>> internal mutex on condition_variable. The associated patch don't
>>> modifies this point. The resolution don't states nothing more than the
>>> ticket has been solved but no how. Please could you explain this
>>> addition? Is this related to another ticket?
>>
>> The patch attached to the ticket is incomplete. There is no requirement
>> that the same mutex is used with the same condition variable instance
>> for every wait. Therefore, if a thread waits with one mutex, wakes,
>> destroys the mutex and then waits with another then there is a race
>> condition with another thread that tries to interrupt it --- the
>> interrupting thread might try and lock a just-destroyed mutex.
>
> Oh, I see. So to support interruptions, the condition variable needs
> to be associated to a single mutex which must be locked before any
> condition variable wait. I don't understand however why do you need
> to lock the mutex each time you signal the condition

If another thread locks the external mutex and then calls notify_one()
then either (a) the waiting thread must be waiting (and will therefore
wake), or (b) it has not yet locked the mutex (and so hasn't started
waiting). In order to preserve the atomicity of the unlock-and-wait
from the point of view of the notifying code, the internal mutex must be
locked when calling pthread_cond_signal, since the external mutex is
unlocked before the call to pthread_cond_wait.

> I was wondering why do we need to pass a unique_lock to the wait
> operations if it is not needed at all?

It *is* needed --- the external mutex is not unlocked until *after* the
internal mutex has been locked.
  
> If I remember the restriction on condition_variable was to be able to
> be as efficient as if we used the underlying platform. If we don't
> have any advantage for condition_variable, why to have it? As not all
> applications use the interruption mechanism, I will preserv a
> condition_variable class that is not an interruption point and is as
> efficient as possible.

It's a trade off.

boost::condition_variable::wait has always been advertised as an
interruption point, and in most cases it has worked. Unfortunately,
there was a race condition on POSIX that sometimes caused it to not see
the interrupt until after being woken. Fixing the race condition
requires adding an internal mutex, which will have a performance impact.

Removing condition_variable::wait() as an interruption point will break
people's code where they have been relying on it. This will be the worst
kind of breakage --- silent breakage, since the external interface would
not have changed in any way. Windows programmers would also lose the
facility, even though it has always worked on Windows.

Anthony

-- 
Author of C++ Concurrency in Action     http://www.stdthread.co.uk/book/
just::thread C++0x thread library             http://www.stdthread.co.uk
Just Software Solutions Ltd       http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk