
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...
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.