
On Oct 8, 2006, at 5:29 AM, Anthony Williams wrote:
3) I don't like the lock(), unlock() etc member functions being public.. forcing scoped_lock is a great cheap idiom for exception safety and saving people from deadlocks. Even with scoped_lock also available - it isn't something found in other languages so I fear new developers will flock to using the simpler and more familiar public members instead.
Howard's proposal has them as public members, so that's what I implemented.
I can see the arguments both ways. Making the functions private is easy, and what boost does already.
There are certainly use cases where pure scoped locks get in the way.
The motivation for making them public in N2094 is that to support those use cases where scoped locking is not the desired behavior. Simply saying that if you want to lock/unlock a mutex in a non-scope pattern then install it in a lock, essentially confuses what a lock is. condition is an example application that needs to lock/unlock a mutex in a non-scoped pattern. boost solves this problem by making condition a friend of the mutex (if I recall correctly). Can it really be true that condition is the only application in need of this service? Don't get me wrong, scoped_lock is great. It is not only the safest way to use a mutex, it is also the easiest. And for most use cases it is exactly what is needed. It is just that scoped_lock isn't the only way to use a mutex. Here are some of the features enabled in N2094 by making mutex::lock/ unlock public: * Clients can write their own mutex types which conform to this concept. * condition can be made to work with any lock *or mutex* which conforms (including client written mutexes). I.e. condition<Mutex>. * Code which is generic in its mutex can be written. Examples include mutex adaptors that turn one type of mutex into another (recursive_mutex_adaptor<Mutex>). Here's another one that makes the "read lock" interface of a read/write mutex look like lock/unlock: template <class Mutex> class sharable_adaptor { private: Mutex& mut_; public: explicit sharable_adaptor(Mutex& mut) : mut_(mut) {} void lock() {mut_.lock_sharable();} bool try_lock() {return mut_.try_lock_sharable();} void unlock() {mut_.unlock_sharable();} }; Now you can use condition variables with a read-locked mutex. --- If safety is easy, it will be used most of the time. If safety is mandated, programmers will be forced into expensive or excessively dangerous workarounds for unanticipated use cases. -Howard