|
Boost : |
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2007-11-15 12:15:39
On Nov 15, 2007, at 10:24 AM, Alexander Terekhov wrote:
>
> Howard Hinnant wrote:
>>
>> On Nov 15, 2007, at 7:02 AM, Alexander Terekhov wrote:
>>
>>>> http://svn.boost.org/svn/boost/trunk/boost/thread/pthread/condition_variable.hpp
>>>
>>> That condition_variable_any wrapper doesn't ensure same destruction
>>> safety of condition varaible as POSIX pthread_cond_t. That's not
>>> good.
>>
>> Thanks for this observation Alexander. Do you have a recommendation
>> for fixing it? The best I'm coming up with at the moment is to
>> keep a
>> count of waiters as member data and have ~condition_variable_any()
>> wait until the count drops to zero.
>
> Or simply use shared_ptr<pthread_mutex_t> for internal_mutex. Peter
> will like that. :-)
:-)
Thanks Alexander. I've been debugging this beast for years now.
Maybe, just maybe, it's debugged now. :-)
struct __lock_external
{
template <class _Lock>
void operator()(_Lock* __m) {__m->lock();}
};
class condition_variable_any
{
condition_variable cv_;
shared_ptr<mutex> mut_;
public:
condition_variable_any() : mut_(new mutex) {}
// ~condition_variable_any() = default;
// condition_variable_any(const condition_variable_any&) = delete;
// condition_variable_any& operator=(const
condition_variable_any&) = delete;
void notify_one();
void notify_all();
template <class Lock>
void wait(Lock& lock);
template <class Lock, class Predicate>
void wait(Lock& lock, Predicate pred);
template <class Lock>
bool timed_wait(Lock& lock, const system_time& abs_time);
template <class Lock, class Predicate>
bool timed_wait(Lock& lock, const system_time& abs_time,
Predicate pred);
template <class Lock, class Duration, class Predicate>
bool timed_wait(Lock& lock, const Duration& rel_time,
Predicate pred);
};
inline
void
condition_variable_any::notify_one()
{
lock_guard<mutex> _(*mut_);
cv_.notify_one();
}
inline
void
condition_variable_any::notify_all()
{
lock_guard<mutex> _(*mut_);
cv_.notify_all();
}
template <class Lock>
void
condition_variable_any::wait(Lock& lock)
{
shared_ptr<mutex> mut = mut_;
unique_lock<mutex> lk(*mut);
lock.unlock();
unique_ptr<Lock, __lock_external> external_guard(&lock);
lock_guard<unique_lock<mutex>> internal_guard(lk, adopt_lock);
cv_.wait(lk);
} // mut_.unlock(), lock.lock()
template <class Lock, class Predicate>
inline
void
condition_variable_any::wait(Lock& lock, Predicate pred)
{
while (!pred())
wait(lock);
}
template <class Lock>
bool
condition_variable_any::timed_wait(Lock& lock, const system_time&
abs_time)
{
shared_ptr<mutex> mut = mut_;
unique_lock<mutex> lk(*mut);
lock.unlock();
unique_ptr<Lock, __lock_external> external_guard(&lock);
lock_guard<unique_lock<mutex>> internal_guard(lk, adopt_lock);
return cv_.timed_wait(lk, abs_time);
} // mut_.unlock(), lock.lock()
template <class Lock, class Predicate>
inline
bool
condition_variable_any::timed_wait(Lock& lock, const system_time&
abs_time, Predicate pred)
{
while (!pred())
if (!timed_wait(lock, abs_time))
return pred();
return true;
}
template <class Lock, class Duration, class Predicate>
inline
bool
condition_variable_any::timed_wait(Lock& lock, const Duration&
rel_time, Predicate pred)
{
return timed_wait(lock, get_system_time() + rel_time,
std::move(pred));
}
> BTW, condition_variable_any's (timed_}wait() above doesn't seem to
> m.lock() in the case of threads cancel (interruption). That doesn't
> match POSIX (and condition_variable thin wrapper) behavior.
<nod>
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk