Boost logo

Boost :

From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2007-11-15 13:56:58


Howard Hinnant wrote:
>
> 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_;
*/

The next step is to ask Peter to generalize a bit his shared_ptr so that
it can use *mut_ itself for refcount sync.

       special_sync_shared_ptr<mutex> mut_;

or some such. (Details omitted for brevity. :-) )

> public:
>
> condition_variable_any() : mut_(new mutex) {}
> // ~condition_variable_any() = default;

Effect on mut_: mut_.reset_with_sync_on(unique_lock<mutex>(*mut_)) so to
speak.

>
> // 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();
> }

No need to hold the lock while signaling. I'd add {}.

>
> inline
> void
> condition_variable_any::notify_all()
> {
> lock_guard<mutex> _(*mut_);
> cv_.notify_all();
> }

No need to hold the lock while signaling. I'd add {}.

>
> template <class Lock>
> void
> condition_variable_any::wait(Lock& lock)
> {

/*
> shared_ptr<mutex> mut = mut_;
> unique_lock<mutex> lk(*mut);
*/

       special_sync_shared_ptr<mutex>::unique_lock_and_addref lk(mut);

> lock.unlock();
> unique_ptr<Lock, __lock_external> external_guard(&lock);

/*
> lock_guard<unique_lock<mutex>> internal_guard(lk, adopt_lock);
*/

Put here something to adopt "unique_lock_and_addref lk" above.

> cv_.wait(lk);
> } // mut_.unlock(), lock.lock()

// unref, unlock mutex, delete mutex if refcount reached zero, lock.lock()

regards,
alexander.


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