
Howard Hinnant wrote:
Here is a link to a reference implementation and a FAQ for mutexes, locks and condition variables I am currently anticipating proposing for C++ standardization (or subsequent TR).
http://home.twcny.rr.com/hinnant/cpp_extensions/concurrency_rationale.html
After some not-so-thorough reading of this, a few comments: 1. I couldn't understand what defer_lock is good for, even after reading Q.9 of the FAQ. I believe the use-case shown in Q.9 should actually use accept_ownership instead. Can you elaborate please? 2. I disagree with the answer to Q.14. I think that shared_mutex should be changed to something like: class shareable_mutex { public: class exclusive_facade { shareable_mutex &__m; public: exclusive_facade(shareable_mutex &m) : __m(m) { } void lock(); bool try_lock(); void unlock(); }; class shared_facade { shareable_mutex &__m; public: shared_facade(shareable_mutex &m) : __m(m) { } void lock(); bool try_lock(); void unlock(); }; exclusive_facade &exclusive(); shared_facade &shared(); }; This way, the condition c'tor will not get the shareable_mutex, but rather the exclusive_facade or the shared_facade, which model Mutex. condition::wait() can then simply call Mutex::unlock(). An additional benefit (additional to having wait() not accept a lock) is that shared_lock can then be dropped, but I haven't really thought about how well this idea works with upgrade_mutex/upgrade_lock. 3. A really minor thing - you suggest a mutex_debug class to ensure we're not using the platform's mutex-recursiveness. I strongly recommend using this when developing on Windows, but there's a actually a simpler way, IMO, to write it (without comparing thread ids): template <class Mutex> class non_recursive_assert_mutex { Mutex mut_; bool locked_; public: non_recursive_assert_mutex() : mut_(), locked_(false) { } void lock() { mut_.lock(); assert(!locked_); locked_ = true; } bool try_lock() { if (mut_.try_lock()) { assert(!locked_); locked_ = true; return true; } return false; } void unlock() { locked_ = false; mut_.unlock(); } };